From 58a83f445a5d1be8a9d0fb6d0f0332e168966875 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Thu, 19 Mar 2026 12:44:08 +0800 Subject: [PATCH] fix: improve doc link navigation and tree display - Fix link resolution with proper relative/absolute path handling - Improve link styling with underline decoration - Hide leaf nodes from tree, only show directories - Fix log file path for packaged app --- .trae/documents/fix_doc_link_matching_plan.md | 82 + .trae/documents/fix_link_color_plan.md | 68 + .trae/documents/fix_link_navigation_plan.md | 57 + .trae/documents/hide_leaf_nodes_plan.md | 39 + docs/api/containers/array/array.md | 67 + docs/api/containers/array/clear.md | 36 + docs/api/containers/array/constructor.md | 44 + .../containers/array/copy-move-constructor.md | 44 + docs/api/containers/array/data.md | 30 + docs/api/containers/array/destructor.md | 28 + docs/api/containers/array/emplaceback.md | 47 + docs/api/containers/array/front-back.md | 38 + docs/api/containers/array/iterator.md | 45 + docs/api/containers/array/operator-assign.md | 44 + .../containers/array/operator-subscript.md | 39 + docs/api/containers/array/popback.md | 38 + docs/api/containers/array/pushback.md | 43 + docs/api/containers/array/reserve.md | 39 + docs/api/containers/array/resize.md | 46 + docs/api/containers/array/setallocator.md | 38 + docs/api/containers/array/size.md | 47 + docs/api/containers/containers.md | 57 + docs/api/containers/hashmap/clear.md | 34 + docs/api/containers/hashmap/constructor.md | 31 + docs/api/containers/hashmap/contains.md | 35 + docs/api/containers/hashmap/copy-move.md | 34 + docs/api/containers/hashmap/destructor.md | 27 + docs/api/containers/hashmap/erase.md | 37 + docs/api/containers/hashmap/find.md | 39 + docs/api/containers/hashmap/hashmap.md | 80 + docs/api/containers/hashmap/insert.md | 38 + docs/api/containers/hashmap/iterator.md | 34 + .../api/containers/hashmap/operator-assign.md | 36 + .../containers/hashmap/operator-subscript.md | 33 + docs/api/containers/hashmap/setallocator.md | 28 + docs/api/containers/hashmap/size.md | 35 + docs/api/containers/string/clear.md | 39 + docs/api/containers/string/constructor.md | 48 + docs/api/containers/string/cstr.md | 36 + docs/api/containers/string/destructor.md | 31 + docs/api/containers/string/ends-with.md | 39 + docs/api/containers/string/find.md | 47 + docs/api/containers/string/operator-assign.md | 47 + docs/api/containers/string/operator-equal.md | 43 + .../containers/string/operator-plus-assign.md | 43 + docs/api/containers/string/operator-plus.md | 39 + .../containers/string/operator-subscript.md | 51 + docs/api/containers/string/reserve-resize.md | 51 + docs/api/containers/string/size.md | 44 + docs/api/containers/string/starts-with.md | 39 + docs/api/containers/string/string.md | 105 + docs/api/containers/string/substring.md | 43 + docs/api/containers/string/to-lower-upper.md | 36 + docs/api/containers/string/trim.md | 35 + docs/api/core/core.md | 97 + docs/api/core/event/Clear.md | 39 + docs/api/core/event/Invoke.md | 45 + docs/api/core/event/ProcessUnsubscribes.md | 39 + docs/api/core/event/Subscribe.md | 50 + docs/api/core/event/Unsubscribe.md | 43 + docs/api/core/event/begin.md | 37 + docs/api/core/event/end.md | 36 + docs/api/core/event/event.md | 69 + docs/api/core/filewriter/Close.md | 40 + docs/api/core/filewriter/Flush.md | 45 + docs/api/core/filewriter/IsOpen.md | 43 + docs/api/core/filewriter/Open.md | 53 + docs/api/core/filewriter/Write.md | 48 + docs/api/core/filewriter/filewriter.md | 66 + docs/api/core/refcounted/AddRef.md | 40 + docs/api/core/refcounted/GetRefCount.md | 43 + docs/api/core/refcounted/Release.md | 39 + docs/api/core/refcounted/refcounted.md | 44 + docs/api/core/smartptr/MakeRef.md | 51 + docs/api/core/smartptr/MakeUnique.md | 49 + docs/api/core/smartptr/Ref.md | 40 + docs/api/core/smartptr/UniqueRef.md | 46 + docs/api/core/smartptr/smartptr.md | 64 + docs/api/core/types/byte.md | 30 + docs/api/core/types/int16.md | 27 + docs/api/core/types/int32.md | 30 + docs/api/core/types/int64.md | 30 + docs/api/core/types/int8.md | 28 + docs/api/core/types/types.md | 63 + docs/api/core/types/uint16.md | 30 + docs/api/core/types/uint32.md | 30 + docs/api/core/types/uint64.md | 30 + docs/api/core/types/uint8.md | 30 + .../debug/consolelogsink/consolelogsink.md | 21 + docs/api/debug/consolelogsink/flush.md | 22 + docs/api/debug/consolelogsink/log.md | 25 + docs/api/debug/consolelogsink/overview.md | 41 + .../debug/consolelogsink/setcoloroutput.md | 24 + .../debug/consolelogsink/setminimumlevel.md | 24 + .../debug/consolelogsink/~consolelogsink.md | 13 + docs/api/debug/debug.md | 86 + docs/api/debug/filelogsink/construct.md | 24 + docs/api/debug/filelogsink/filelogsink.md | 37 + docs/api/debug/filelogsink/flush.md | 24 + docs/api/debug/filelogsink/log.md | 25 + docs/api/debug/filelogsink/~filelogsink.md | 13 + docs/api/debug/ilogsink/flush.md | 32 + docs/api/debug/ilogsink/ilogsink.md | 45 + docs/api/debug/ilogsink/log.md | 29 + docs/api/debug/logcategory/logcategory.md | 44 + .../debug/logcategory/logcategorytostring.md | 28 + docs/api/debug/logentry/logentry.md | 47 + docs/api/debug/logger/addsink.md | 27 + docs/api/debug/logger/debug.md | 30 + docs/api/debug/logger/error.md | 30 + docs/api/debug/logger/fatal.md | 30 + docs/api/debug/logger/get.md | 22 + docs/api/debug/logger/info.md | 30 + docs/api/debug/logger/initialize.md | 28 + docs/api/debug/logger/log.md | 45 + docs/api/debug/logger/logger.md | 92 + docs/api/debug/logger/removesink.md | 29 + docs/api/debug/logger/setcategoryenabled.md | 36 + docs/api/debug/logger/setminimumlevel.md | 30 + docs/api/debug/logger/shutdown.md | 26 + docs/api/debug/logger/verbose.md | 30 + docs/api/debug/logger/warning.md | 30 + docs/api/debug/loglevel/loglevel.md | 40 + docs/api/debug/loglevel/logleveltostring.md | 28 + docs/api/debug/profiler/beginframe.md | 26 + docs/api/debug/profiler/beginprofile.md | 36 + docs/api/debug/profiler/endframe.md | 26 + docs/api/debug/profiler/endprofile.md | 25 + .../api/debug/profiler/exportchrometracing.md | 45 + docs/api/debug/profiler/get.md | 22 + docs/api/debug/profiler/initialize.md | 30 + docs/api/debug/profiler/markevent.md | 36 + docs/api/debug/profiler/profiler.md | 136 + docs/api/debug/profiler/setmarker.md | 33 + docs/api/debug/profiler/shutdown.md | 22 + docs/api/fix_links.py | 238 + docs/api/main.md | 94 + docs/api/math/aabb/aabb.md | 43 + docs/api/math/aabb/getaxis.md | 23 + docs/api/math/aabb/intersects-obb.md | 24 + docs/api/math/aabb/intersects-sphere.md | 24 + docs/api/math/aabb/obb-contains.md | 20 + docs/api/math/aabb/obb-getaxis.md | 20 + docs/api/math/aabb/obb-getmax.md | 17 + docs/api/math/aabb/obb-getmin.md | 17 + docs/api/math/aabb/obb-intersects-obb.md | 25 + docs/api/math/aabb/obb-intersects-sphere.md | 28 + docs/api/math/bounds/bounds.md | 40 + docs/api/math/bounds/contains.md | 20 + docs/api/math/bounds/encapsulate-bounds.md | 18 + docs/api/math/bounds/encapsulate.md | 21 + docs/api/math/bounds/expand.md | 19 + docs/api/math/bounds/getclosestpoint.md | 20 + docs/api/math/bounds/getmax.md | 17 + docs/api/math/bounds/getmin.md | 17 + docs/api/math/bounds/getvolume.md | 17 + docs/api/math/bounds/intersects.md | 20 + docs/api/math/bounds/setminmax.md | 19 + docs/api/math/box/box.md | 44 + docs/api/math/box/contains.md | 20 + docs/api/math/box/getmax.md | 17 + docs/api/math/box/getmin.md | 17 + docs/api/math/box/intersects-box.md | 22 + docs/api/math/box/intersects-ray.md | 24 + docs/api/math/box/intersects.md | 20 + docs/api/math/color/black.md | 11 + docs/api/math/color/blue.md | 11 + docs/api/math/color/clear.md | 11 + docs/api/math/color/color.md | 64 + docs/api/math/color/cyan.md | 11 + docs/api/math/color/green.md | 11 + docs/api/math/color/lerp.md | 22 + docs/api/math/color/magenta.md | 11 + docs/api/math/color/red.md | 11 + docs/api/math/color/torgba.md | 18 + docs/api/math/color/tovector3.md | 17 + docs/api/math/color/tovector4.md | 17 + docs/api/math/color/white.md | 11 + docs/api/math/color/yellow.md | 11 + docs/api/math/frustum/contains-bounds.md | 25 + docs/api/math/frustum/contains-point.md | 24 + docs/api/math/frustum/contains-sphere.md | 24 + docs/api/math/frustum/frustum.md | 45 + docs/api/math/frustum/intersects-bounds.md | 26 + docs/api/math/frustum/intersects-sphere.md | 25 + docs/api/math/h/deg-to-rad.md | 20 + docs/api/math/h/degrees.md | 20 + docs/api/math/h/epsilon.md | 23 + docs/api/math/h/float-max.md | 19 + docs/api/math/h/h.md | 54 + docs/api/math/h/half-pi.md | 19 + docs/api/math/h/pi.md | 22 + docs/api/math/h/rad-to-deg.md | 20 + docs/api/math/h/radians.md | 20 + docs/api/math/h/two-pi.md | 19 + docs/api/math/math.md | 100 + docs/api/math/matrix3/determinant.md | 18 + docs/api/math/matrix3/identity.md | 17 + docs/api/math/matrix3/inverse.md | 18 + docs/api/math/matrix3/matrix3.md | 57 + docs/api/math/matrix3/rotationx.md | 20 + docs/api/math/matrix3/rotationy.md | 20 + docs/api/math/matrix3/rotationz.md | 20 + docs/api/math/matrix3/scale.md | 20 + docs/api/math/matrix3/transpose.md | 18 + docs/api/math/matrix3/zero.md | 17 + docs/api/math/matrix4/decompose.md | 24 + docs/api/math/matrix4/determinant.md | 18 + docs/api/math/matrix4/getrotation.md | 18 + docs/api/math/matrix4/getscale.md | 18 + docs/api/math/matrix4/gettranslation.md | 18 + docs/api/math/matrix4/identity.md | 17 + docs/api/math/matrix4/inverse.md | 18 + docs/api/math/matrix4/lookat.md | 22 + docs/api/math/matrix4/matrix4.md | 79 + docs/api/math/matrix4/multiplypoint.md | 21 + docs/api/math/matrix4/multiplyvector.md | 21 + docs/api/math/matrix4/orthographic.md | 25 + docs/api/math/matrix4/perspective.md | 23 + docs/api/math/matrix4/rotation.md | 21 + docs/api/math/matrix4/rotationx.md | 20 + docs/api/math/matrix4/rotationy.md | 20 + docs/api/math/matrix4/rotationz.md | 20 + docs/api/math/matrix4/scale.md | 20 + docs/api/math/matrix4/translation.md | 20 + docs/api/math/matrix4/transpose.md | 18 + docs/api/math/matrix4/trs.md | 22 + docs/api/math/matrix4/zero.md | 17 + docs/api/math/plane/frompoints.md | 22 + docs/api/math/plane/getclosestpoint.md | 20 + docs/api/math/plane/getdistancetopoint.md | 20 + docs/api/math/plane/getside.md | 20 + docs/api/math/plane/intersects.md | 20 + docs/api/math/plane/plane.md | 40 + docs/api/math/quaternion/dot.md | 20 + docs/api/math/quaternion/fromaxisangle.md | 21 + docs/api/math/quaternion/fromeulerangles.md | 25 + .../api/math/quaternion/fromrotationmatrix.md | 21 + docs/api/math/quaternion/identity.md | 17 + docs/api/math/quaternion/inverse.md | 17 + docs/api/math/quaternion/lookrotation.md | 21 + docs/api/math/quaternion/magnitude.md | 17 + docs/api/math/quaternion/normalized.md | 40 + .../math/quaternion/quaternion-multiply.md | 23 + docs/api/math/quaternion/quaternion.md | 61 + docs/api/math/quaternion/slerp.md | 22 + docs/api/math/quaternion/toeulerangles.md | 18 + docs/api/math/quaternion/tomatrix4x4.md | 18 + docs/api/math/ray/getpoint.md | 22 + docs/api/math/ray/intersects-box.md | 27 + docs/api/math/ray/intersects-plane.md | 27 + docs/api/math/ray/intersects-sphere.md | 26 + docs/api/math/ray/ray.md | 44 + docs/api/math/rect/contains-float.md | 24 + docs/api/math/rect/contains-vector2.md | 24 + docs/api/math/rect/getbottom.md | 18 + docs/api/math/rect/getcenter.md | 18 + docs/api/math/rect/getleft.md | 18 + docs/api/math/rect/getposition.md | 18 + docs/api/math/rect/getright.md | 18 + docs/api/math/rect/getsize.md | 18 + docs/api/math/rect/gettop.md | 18 + docs/api/math/rect/intersect.md | 23 + docs/api/math/rect/intersects.md | 24 + docs/api/math/rect/rect-overview.md | 69 + docs/api/math/rect/rect.md | 17 + docs/api/math/rect/rectint-contains.md | 24 + docs/api/math/rect/rectint-getbottom.md | 18 + docs/api/math/rect/rectint-getcenter.md | 18 + docs/api/math/rect/rectint-getleft.md | 18 + docs/api/math/rect/rectint-getposition.md | 18 + docs/api/math/rect/rectint-getright.md | 18 + docs/api/math/rect/rectint-getsize.md | 18 + docs/api/math/rect/rectint-gettop.md | 18 + docs/api/math/rect/rectint-intersects.md | 24 + docs/api/math/rect/rectint.md | 53 + docs/api/math/rect/set.md | 24 + docs/api/math/rect/setposition-float.md | 22 + docs/api/math/rect/setposition-vector2.md | 21 + docs/api/math/rect/union.md | 23 + docs/api/math/rect/viewport-getaspectratio.md | 18 + docs/api/math/rect/viewport-getrect.md | 18 + docs/api/math/rect/viewport.md | 45 + docs/api/math/sphere/contains.md | 20 + docs/api/math/sphere/intersects.md | 20 + docs/api/math/sphere/sphere.md | 32 + docs/api/math/transform/inverse.md | 17 + .../transform/inversetransformdirection.md | 21 + .../math/transform/inversetransformpoint.md | 21 + docs/api/math/transform/tomatrix.md | 19 + docs/api/math/transform/transform.md | 39 + docs/api/math/transform/transformdirection.md | 22 + docs/api/math/transform/transformpoint.md | 22 + docs/api/math/vector2/cross.md | 23 + docs/api/math/vector2/dot.md | 23 + docs/api/math/vector2/down.md | 17 + docs/api/math/vector2/left.md | 17 + docs/api/math/vector2/lerp.md | 24 + docs/api/math/vector2/magnitude.md | 25 + docs/api/math/vector2/movetowards.md | 24 + docs/api/math/vector2/normalize.md | 20 + docs/api/math/vector2/normalized.md | 18 + docs/api/math/vector2/one.md | 17 + docs/api/math/vector2/right.md | 17 + docs/api/math/vector2/sqrmagnitude.md | 25 + docs/api/math/vector2/up.md | 17 + docs/api/math/vector2/vector2.md | 57 + docs/api/math/vector2/zero.md | 17 + docs/api/math/vector3/angle.md | 23 + docs/api/math/vector3/back.md | 17 + docs/api/math/vector3/cross.md | 23 + docs/api/math/vector3/dot.md | 23 + docs/api/math/vector3/down.md | 17 + docs/api/math/vector3/forward.md | 17 + docs/api/math/vector3/left.md | 17 + docs/api/math/vector3/lerp.md | 24 + docs/api/math/vector3/magnitude.md | 25 + docs/api/math/vector3/movetowards.md | 24 + docs/api/math/vector3/normalize.md | 20 + docs/api/math/vector3/normalized.md | 18 + docs/api/math/vector3/one.md | 17 + docs/api/math/vector3/project.md | 23 + docs/api/math/vector3/projectonplane.md | 23 + docs/api/math/vector3/quaternion-multiply.md | 23 + docs/api/math/vector3/reflect.md | 23 + docs/api/math/vector3/right.md | 17 + docs/api/math/vector3/sqrmagnitude.md | 25 + docs/api/math/vector3/up.md | 17 + docs/api/math/vector3/vector3.md | 69 + docs/api/math/vector3/zero.md | 17 + docs/api/math/vector4/dot.md | 23 + docs/api/math/vector4/one.md | 17 + docs/api/math/vector4/project.md | 23 + docs/api/math/vector4/tovector3.md | 18 + docs/api/math/vector4/vector4.md | 53 + docs/api/math/vector4/zero.md | 17 + docs/api/memory/allocator/allocate.md | 38 + docs/api/memory/allocator/allocator.md | 72 + docs/api/memory/allocator/free.md | 40 + .../memory/allocator/get-allocation-count.md | 52 + docs/api/memory/allocator/get-name.md | 40 + .../memory/allocator/get-peak-allocated.md | 57 + .../memory/allocator/get-total-allocated.md | 50 + docs/api/memory/allocator/get-total-freed.md | 50 + docs/api/memory/allocator/reallocate.md | 55 + docs/api/memory/linear-allocator/allocate.md | 41 + docs/api/memory/linear-allocator/clear.md | 37 + docs/api/memory/linear-allocator/free.md | 35 + .../memory/linear-allocator/get-capacity.md | 33 + .../api/memory/linear-allocator/get-marker.md | 43 + .../memory/linear-allocator/get-used-size.md | 39 + .../linear-allocator/linear-allocator.md | 66 + .../api/memory/linear-allocator/reallocate.md | 35 + .../api/memory/linear-allocator/set-marker.md | 41 + .../linear-allocator/~linear-allocator.md | 29 + .../memory/manager/create-linear-allocator.md | 32 + .../memory/manager/create-pool-allocator.md | 37 + .../memory/manager/create-proxy-allocator.md | 36 + docs/api/memory/manager/dump-memory-leaks.md | 31 + .../memory/manager/generate-memory-report.md | 37 + .../memory/manager/get-system-allocator.md | 27 + docs/api/memory/manager/get.md | 39 + docs/api/memory/manager/initialize.md | 33 + docs/api/memory/manager/manager.md | 85 + .../memory/manager/set-track-allocations.md | 35 + docs/api/memory/manager/shutdown.md | 35 + docs/api/memory/memory.md | 72 + docs/api/memory/pool-allocator/allocate.md | 38 + docs/api/memory/pool-allocator/contains.md | 38 + docs/api/memory/pool-allocator/free.md | 38 + .../memory/pool-allocator/get-block-size.md | 31 + .../pool-allocator/get-free-block-count.md | 40 + .../pool-allocator/get-total-block-count.md | 34 + .../memory/pool-allocator/pool-allocator.md | 73 + docs/api/memory/pool-allocator/reallocate.md | 35 + .../memory/pool-allocator/~pool-allocator.md | 31 + docs/api/memory/proxy-allocator/allocate.md | 37 + docs/api/memory/proxy-allocator/free.md | 42 + docs/api/memory/proxy-allocator/get-stats.md | 40 + .../memory/proxy-allocator/proxy-allocator.md | 61 + docs/api/memory/proxy-allocator/reallocate.md | 38 + .../proxy-allocator/~proxy-allocator.md | 37 + docs/api/resources/asyncloader/asyncloader.md | 107 + docs/api/resources/asyncloader/cancelall.md | 26 + docs/api/resources/asyncloader/getprogress.md | 24 + docs/api/resources/asyncloader/submit.md | 35 + docs/api/resources/asyncloader/update.md | 27 + docs/api/resources/audioclip/audioclip.md | 139 + docs/api/resources/audioclip/setaudiodata.md | 29 + .../dependencygraph/adddependency.md | 27 + docs/api/resources/dependencygraph/addnode.md | 27 + .../dependencygraph/dependencygraph.md | 88 + .../dependencygraph/getdependencies.md | 25 + .../dependencygraph/hascirculardependency.md | 31 + .../dependencygraph/topologicalsort.md | 28 + docs/api/resources/filearchive/filearchive.md | 84 + docs/api/resources/filesystem/exists.md | 26 + docs/api/resources/filesystem/filesystem.md | 104 + docs/api/resources/filesystem/initialize.md | 24 + docs/api/resources/filesystem/readresource.md | 27 + docs/api/resources/iloader/canload.md | 31 + .../resources/iloader/getdefaultsettings.md | 25 + .../iloader/getsupportedextensions.md | 25 + docs/api/resources/iloader/iloader.md | 119 + docs/api/resources/iloader/load.md | 42 + docs/api/resources/iloader/loadasync.md | 34 + .../importsettings/importsettings.md | 173 + docs/api/resources/iresource/initialize.md | 34 + docs/api/resources/iresource/iresource.md | 57 + docs/api/resources/iresource/release.md | 33 + docs/api/resources/iresource/setinvalid.md | 28 + docs/api/resources/material/material.md | 151 + docs/api/resources/material/setfloat.md | 27 + docs/api/resources/material/setshader.md | 26 + docs/api/resources/material/settexture.md | 28 + .../material/updateconstantbuffer.md | 26 + docs/api/resources/mesh/addsection.md | 30 + docs/api/resources/mesh/mesh.md | 150 + docs/api/resources/mesh/setindexdata.md | 30 + docs/api/resources/mesh/setvertexdata.md | 37 + docs/api/resources/resourcecache/add.md | 25 + docs/api/resources/resourcecache/flush.md | 23 + .../api/resources/resourcecache/getlrulist.md | 27 + .../resourcecache/onmemorypressure.md | 25 + .../resources/resourcecache/resourcecache.md | 79 + docs/api/resources/resourcecache/touch.md | 27 + docs/api/resources/resourcehandle/get.md | 27 + docs/api/resources/resourcehandle/getguid.md | 27 + docs/api/resources/resourcehandle/isvalid.md | 29 + docs/api/resources/resourcehandle/reset.md | 31 + .../resourcehandle/resourcehandle.md | 74 + docs/api/resources/resourcehandle/swap.md | 30 + docs/api/resources/resourcemanager/exists.md | 28 + docs/api/resources/resourcemanager/find.md | 29 + .../resources/resourcemanager/getloader.md | 27 + docs/api/resources/resourcemanager/load.md | 32 + .../resources/resourcemanager/loadasync.md | 44 + .../resources/resourcemanager/loadgroup.md | 35 + .../resourcemanager/registerloader.md | 26 + .../resourcemanager/resourcemanager.md | 101 + .../resourcemanager/setmemorybudget.md | 24 + docs/api/resources/resourcemanager/unload.md | 31 + .../resources/resourcemanager/unloadunused.md | 26 + .../resourcepackage/resourcepackage.md | 161 + .../resources/resourcepath/resourcepath.md | 87 + docs/api/resources/resources.md | 95 + docs/api/resources/resourcetypes/generate.md | 26 + .../resourcetypes/getresourcetypename.md | 25 + .../resources/resourcetypes/resourcetypes.md | 130 + docs/api/resources/shader/addattribute.md | 29 + docs/api/resources/shader/adduniform.md | 29 + docs/api/resources/shader/shader.md | 154 + docs/api/resources/texture/create.md | 39 + docs/api/resources/texture/generatemipmaps.md | 24 + docs/api/resources/texture/texture.md | 161 + docs/api/rhi/buffer/buffer.md | 86 + docs/api/rhi/buffer/get-buffer-type.md | 15 + docs/api/rhi/buffer/get-name.md | 15 + docs/api/rhi/buffer/get-native-handle.md | 17 + docs/api/rhi/buffer/get-size.md | 15 + docs/api/rhi/buffer/get-state.md | 15 + docs/api/rhi/buffer/get-stride.md | 15 + docs/api/rhi/buffer/map.md | 25 + docs/api/rhi/buffer/set-buffer-type.md | 16 + docs/api/rhi/buffer/set-data.md | 29 + docs/api/rhi/buffer/set-name.md | 22 + docs/api/rhi/buffer/set-state.md | 22 + docs/api/rhi/buffer/set-stride.md | 16 + docs/api/rhi/buffer/shutdown.md | 13 + docs/api/rhi/buffer/unmap.md | 21 + docs/api/rhi/capabilities/capabilities.md | 82 + .../rhi/command-list/clear-depth-stencil.md | 22 + .../rhi/command-list/clear-render-target.md | 22 + docs/api/rhi/command-list/clear.md | 20 + docs/api/rhi/command-list/close.md | 13 + docs/api/rhi/command-list/command-list.md | 55 + docs/api/rhi/command-list/copy-resource.md | 21 + docs/api/rhi/command-list/dispatch.md | 22 + docs/api/rhi/command-list/draw-indexed.md | 24 + docs/api/rhi/command-list/draw.md | 23 + docs/api/rhi/command-list/methods.md | 201 + docs/api/rhi/command-list/reset.md | 13 + docs/api/rhi/command-list/set-blend-factor.md | 21 + docs/api/rhi/command-list/set-blend-state.md | 23 + .../command-list/set-depth-stencil-state.md | 24 + docs/api/rhi/command-list/set-index-buffer.md | 22 + .../rhi/command-list/set-pipeline-state.md | 20 + .../command-list/set-primitive-topology.md | 20 + .../rhi/command-list/set-render-targets.md | 23 + docs/api/rhi/command-list/set-scissor-rect.md | 25 + .../api/rhi/command-list/set-scissor-rects.md | 24 + docs/api/rhi/command-list/set-stencil-ref.md | 20 + .../api/rhi/command-list/set-vertex-buffer.md | 23 + .../rhi/command-list/set-vertex-buffers.md | 27 + docs/api/rhi/command-list/set-viewport.md | 27 + docs/api/rhi/command-list/set-viewports.md | 24 + docs/api/rhi/command-list/shutdown.md | 13 + .../rhi/command-list/transition-barrier.md | 23 + docs/api/rhi/command-queue/command-queue.md | 50 + .../command-queue/execute-command-lists.md | 22 + .../rhi/command-queue/get-completed-value.md | 19 + .../rhi/command-queue/get-native-handle.md | 15 + .../command-queue/get-timestamp-frequency.md | 19 + docs/api/rhi/command-queue/get-type.md | 15 + docs/api/rhi/command-queue/methods.md | 73 + docs/api/rhi/command-queue/shutdown.md | 13 + docs/api/rhi/command-queue/signal.md | 21 + docs/api/rhi/command-queue/wait-for-idle.md | 17 + docs/api/rhi/d3d12/buffer/buffer.md | 37 + docs/api/rhi/d3d12/buffer/get-buffer-type.md | 16 + docs/api/rhi/d3d12/buffer/get-desc.md | 19 + docs/api/rhi/d3d12/buffer/get-gpu-address.md | 19 + .../d3d12/buffer/get-gpu-virtual-address.md | 19 + docs/api/rhi/d3d12/buffer/get-name.md | 16 + .../api/rhi/d3d12/buffer/get-native-handle.md | 19 + docs/api/rhi/d3d12/buffer/get-resource.md | 19 + docs/api/rhi/d3d12/buffer/get-size.md | 19 + docs/api/rhi/d3d12/buffer/get-state.md | 16 + docs/api/rhi/d3d12/buffer/get-stride.md | 16 + .../d3d12/buffer/initialize-from-existing.md | 35 + .../rhi/d3d12/buffer/initialize-with-data.md | 42 + docs/api/rhi/d3d12/buffer/initialize.md | 39 + docs/api/rhi/d3d12/buffer/map.md | 27 + docs/api/rhi/d3d12/buffer/set-data.md | 23 + docs/api/rhi/d3d12/buffer/shutdown.md | 15 + docs/api/rhi/d3d12/buffer/unmap.md | 15 + docs/api/rhi/d3d12/buffer/update-data.md | 28 + .../command-allocator/command-allocator.md | 19 + .../get-command-allocator.md | 15 + .../rhi/d3d12/command-allocator/is-ready.md | 15 + .../rhi/d3d12/command-list/alias-barrier.md | 17 + .../api/rhi/d3d12/command-list/begin-query.md | 18 + .../d3d12/command-list/clear-depth-stencil.md | 18 + .../d3d12/command-list/clear-render-target.md | 17 + .../rhi/d3d12/command-list/command-list.md | 65 + .../api/rhi/d3d12/command-list/copy-buffer.md | 20 + .../rhi/d3d12/command-list/copy-resource.md | 17 + .../rhi/d3d12/command-list/copy-texture.md | 19 + .../d3d12/command-list/dispatch-indirect.md | 17 + docs/api/rhi/d3d12/command-list/dispatch.md | 18 + .../draw-indexed-instanced-indirect.md | 17 + .../rhi/d3d12/command-list/draw-indexed.md | 20 + .../command-list/draw-instanced-indirect.md | 17 + docs/api/rhi/d3d12/command-list/draw.md | 19 + docs/api/rhi/d3d12/command-list/end-query.md | 18 + .../rhi/d3d12/command-list/execute-bundle.md | 16 + .../d3d12/command-list/get-command-list.md | 15 + .../d3d12/command-list/get-resource-state.md | 18 + .../d3d12/command-list/resolve-query-data.md | 21 + .../d3d12/command-list/set-blend-factor.md | 16 + .../set-compute-descriptor-table.md | 17 + .../rhi/d3d12/command-list/set-depth-bias.md | 18 + .../d3d12/command-list/set-descriptor-heap.md | 16 + .../command-list/set-descriptor-heaps.md | 17 + .../set-graphics-descriptor-table.md | 17 + .../set-graphics-root-32bit-constants.md | 19 + .../set-graphics-root-constant-buffer-view.md | 17 + .../set-graphics-root-descriptor-table.md | 17 + .../set-graphics-root-shader-resource-view.md | 17 + .../d3d12/command-list/set-index-buffer.md | 18 + .../d3d12/command-list/set-pipeline-state.md | 16 + .../command-list/set-primitive-topology.md | 16 + .../command-list/set-render-targets-handle.md | 18 + .../set-render-targets-internal.md | 18 + .../d3d12/command-list/set-render-targets.md | 18 + .../d3d12/command-list/set-root-signature.md | 16 + .../d3d12/command-list/set-scissor-rect.md | 16 + .../d3d12/command-list/set-scissor-rects.md | 17 + .../rhi/d3d12/command-list/set-stencil-ref.md | 16 + .../d3d12/command-list/set-vertex-buffer.md | 19 + .../d3d12/command-list/set-vertex-buffers.md | 20 + .../rhi/d3d12/command-list/set-viewport.md | 16 + .../rhi/d3d12/command-list/set-viewports.md | 17 + .../rhi/d3d12/command-list/track-resource.md | 16 + .../transition-barrier-internal.md | 19 + .../d3d12/command-list/transition-barrier.md | 18 + .../api/rhi/d3d12/command-list/uav-barrier.md | 16 + .../rhi/d3d12/command-queue/command-queue.md | 26 + .../command-queue/execute-command-lists.md | 17 + .../d3d12/command-queue/get-command-queue.md | 15 + .../command-queue/get-completed-value.md | 15 + .../command-queue/get-timestamp-frequency.md | 15 + docs/api/rhi/d3d12/command-queue/signal.md | 17 + .../rhi/d3d12/command-queue/wait-for-idle.md | 13 + docs/api/rhi/d3d12/common/common.md | 67 + .../constant-buffer-view.md | 17 + .../get-cpu-descriptor-handle.md | 15 + docs/api/rhi/d3d12/d3d12.md | 77 + .../d3d12/depth-stencil-view/create-desc.md | 19 + .../depth-stencil-view/depth-stencil-view.md | 19 + .../get-cpu-descriptor-handle.md | 15 + .../d3d12/depth-stencil-view/initialize-at.md | 19 + .../rhi/d3d12/descriptor-heap/create-desc.md | 20 + .../d3d12/descriptor-heap/descriptor-heap.md | 27 + ...et-cpu-descriptor-handle-for-heap-start.md | 15 + .../get-cpu-descriptor-handle.md | 18 + .../descriptor-heap/get-descriptor-count.md | 15 + .../descriptor-heap/get-descriptor-heap.md | 15 + .../descriptor-heap/get-descriptor-size.md | 15 + ...et-gpu-descriptor-handle-for-heap-start.md | 15 + .../get-gpu-descriptor-handle.md | 18 + .../descriptor-heap/initialize-from-desc.md | 18 + .../rhi/d3d12/device/check-feature-support.md | 25 + docs/api/rhi/d3d12/device/device.md | 35 + .../rhi/d3d12/device/enumerate-adapters.md | 22 + docs/api/rhi/d3d12/device/get-adapter-info.md | 20 + .../get-descriptor-handle-increment-size.md | 22 + docs/api/rhi/d3d12/device/get-device.md | 19 + docs/api/rhi/d3d12/device/get-factory.md | 19 + docs/api/rhi/d3d12/device/methods.md | 165 + docs/api/rhi/d3d12/enums/enums.md | 37 + docs/api/rhi/d3d12/fence/fence.md | 24 + .../rhi/d3d12/fence/get-completed-value.md | 34 + docs/api/rhi/d3d12/fence/get-event-handle.md | 31 + docs/api/rhi/d3d12/fence/get-fence.md | 30 + docs/api/rhi/d3d12/fence/is-signaled.md | 33 + docs/api/rhi/d3d12/fence/signal.md | 46 + .../rhi/d3d12/pipeline-state/create-desc.md | 53 + .../pipeline-state/create-input-element.md | 54 + .../pipeline-state/get-pipeline-state.md | 29 + .../d3d12/pipeline-state/pipeline-state.md | 24 + docs/api/rhi/d3d12/query-heap/get-count.md | 29 + .../rhi/d3d12/query-heap/get-query-heap.md | 29 + docs/api/rhi/d3d12/query-heap/query-heap.md | 20 + .../d3d12/render-target-view/create-desc.md | 36 + .../get-cpu-descriptor-handle.md | 29 + .../d3d12/render-target-view/initialize-at.md | 40 + .../render-target-view/render-target-view.md | 19 + .../root-signature/create-32bit-constants.md | 38 + .../rhi/d3d12/root-signature/create-cbv.md | 39 + .../rhi/d3d12/root-signature/create-desc.md | 48 + .../root-signature/create-descriptor-range.md | 39 + .../root-signature/create-descriptor-table.md | 40 + .../root-signature/create-sampler-desc.md | 38 + .../rhi/d3d12/root-signature/create-srv.md | 39 + .../root-signature/create-static-sampler.md | 39 + .../rhi/d3d12/root-signature/create-uav.md | 39 + .../root-signature/get-parameter-count.md | 29 + .../root-signature/get-root-signature.md | 29 + .../d3d12/root-signature/root-signature.md | 28 + docs/api/rhi/d3d12/sampler/get-id.md | 29 + docs/api/rhi/d3d12/sampler/sampler.md | 22 + docs/api/rhi/d3d12/screenshot/capture.md | 46 + .../screenshot/copy-to-readback-and-save.md | 46 + docs/api/rhi/d3d12/screenshot/screenshot.md | 16 + .../d3d12/shader-resource-view/create-desc.md | 37 + .../get-cpu-descriptor-handle.md | 29 + .../shader-resource-view/initialize-at.md | 39 + .../shader-resource-view.md | 19 + .../api/rhi/d3d12/shader/get-bytecode-size.md | 30 + docs/api/rhi/d3d12/shader/get-bytecode.md | 30 + .../rhi/d3d12/shader/get-d3d12-bytecode.md | 29 + docs/api/rhi/d3d12/shader/get-input-layout.md | 29 + docs/api/rhi/d3d12/shader/set-uniforms.md | 46 + docs/api/rhi/d3d12/shader/shader.md | 28 + .../rhi/d3d12/swap-chain/get-back-buffer.md | 35 + .../get-current-back-buffer-index.md | 30 + .../swap-chain/get-current-back-buffer.md | 30 + .../rhi/d3d12/swap-chain/get-swap-chain.md | 29 + .../swap-chain/initialize-from-swapchain.md | 40 + .../api/rhi/d3d12/swap-chain/is-fullscreen.md | 32 + docs/api/rhi/d3d12/swap-chain/poll-events.md | 29 + docs/api/rhi/d3d12/swap-chain/present.md | 36 + .../rhi/d3d12/swap-chain/set-fullscreen.md | 36 + .../rhi/d3d12/swap-chain/set-should-close.md | 36 + docs/api/rhi/d3d12/swap-chain/should-close.md | 32 + docs/api/rhi/d3d12/swap-chain/swap-chain.md | 29 + docs/api/rhi/d3d12/texture/get-array-size.md | 29 + .../d3d12/texture/initialize-depth-stencil.md | 38 + .../rhi/d3d12/texture/initialize-from-data.md | 42 + docs/api/rhi/d3d12/texture/texture.md | 35 + .../rhi/d3d12/types/to-d3d12-buffer-desc.md | 36 + .../rhi/d3d12/types/to-d3d12-clear-value.md | 37 + .../types/to-d3d12-command-queue-desc.md | 36 + .../rhi/d3d12/types/to-d3d12-depth-stencil.md | 37 + .../types/to-d3d12-descriptor-heap-desc.md | 36 + .../d3d12/types/to-d3d12-heap-properties.md | 36 + docs/api/rhi/d3d12/types/to-d3d12-rect.md | 36 + .../rhi/d3d12/types/to-d3d12-texture-desc.md | 36 + docs/api/rhi/d3d12/types/to-d3d12-viewport.md | 36 + docs/api/rhi/d3d12/types/types.md | 24 + .../get-cpu-descriptor-handle.md | 29 + .../unordered-access-view.md | 15 + .../rhi/descriptor-pool/descriptor-pool.md | 22 + .../descriptor-pool/get-descriptor-count.md | 19 + docs/api/rhi/descriptor-pool/methods.md | 41 + docs/api/rhi/device/compile-shader.md | 35 + docs/api/rhi/device/create-buffer.md | 32 + docs/api/rhi/device/create-command-list.md | 29 + docs/api/rhi/device/create-command-queue.md | 31 + docs/api/rhi/device/create-fence.md | 29 + docs/api/rhi/device/create-pipeline-state.md | 29 + docs/api/rhi/device/create-sampler.md | 34 + docs/api/rhi/device/create-swap-chain.md | 34 + docs/api/rhi/device/create-texture.md | 38 + docs/api/rhi/device/device.md | 73 + docs/api/rhi/device/get-capabilities.md | 32 + docs/api/rhi/device/get-device-info.md | 27 + docs/api/rhi/device/get-native-device.md | 29 + docs/api/rhi/device/initialize.md | 39 + docs/api/rhi/device/shutdown.md | 20 + docs/api/rhi/enums/enums.md | 46 + .../rhi/factory/create-rhi-device-string.md | 31 + .../api/rhi/factory/create-rhi-device-type.md | 28 + docs/api/rhi/factory/factory.md | 47 + docs/api/rhi/fence/fence.md | 34 + docs/api/rhi/fence/get-completed-value.md | 19 + docs/api/rhi/fence/get-native-handle.md | 15 + docs/api/rhi/fence/is-signaled.md | 21 + docs/api/rhi/fence/methods.md | 50 + docs/api/rhi/fence/shutdown.md | 13 + docs/api/rhi/fence/signal.md | 22 + docs/api/rhi/fence/wait.md | 20 + docs/api/rhi/opengl/README.md | 26 + docs/api/rhi/opengl/buffer/bind-base.md | 21 + docs/api/rhi/opengl/buffer/bind.md | 17 + docs/api/rhi/opengl/buffer/buffer.md | 38 + docs/api/rhi/opengl/buffer/get-id.md | 20 + docs/api/rhi/opengl/buffer/get-type.md | 19 + .../opengl/buffer/initialize-index-buffer.md | 25 + .../opengl/buffer/initialize-vertex-buffer.md | 25 + docs/api/rhi/opengl/buffer/initialize.md | 26 + docs/api/rhi/opengl/buffer/is-dynamic.md | 24 + docs/api/rhi/opengl/buffer/unbind.md | 17 + .../rhi/opengl/command-list/clear-color.md | 23 + .../command-list/clear-depth-stencil.md | 22 + .../rhi/opengl/command-list/clear-depth.md | 20 + .../command-list/clear-render-target.md | 22 + .../rhi/opengl/command-list/clear-stencil.md | 20 + docs/api/rhi/opengl/command-list/clear.md | 24 + .../rhi/opengl/command-list/command-list.md | 44 + .../rhi/opengl/command-list/copy-resource.md | 21 + docs/api/rhi/opengl/command-list/dispatch.md | 22 + .../rhi/opengl/command-list/draw-indexed.md | 24 + docs/api/rhi/opengl/command-list/draw.md | 23 + .../rhi/opengl/command-list/opengl-methods.md | 545 ++ .../opengl/command-list/set-blend-factor.md | 21 + .../opengl/command-list/set-blend-state.md | 24 + .../command-list/set-depth-stencil-state.md | 24 + .../opengl/command-list/set-index-buffer.md | 22 + .../opengl/command-list/set-pipeline-state.md | 20 + .../command-list/set-primitive-topology.md | 20 + .../opengl/command-list/set-render-targets.md | 23 + .../opengl/command-list/set-scissor-rect.md | 23 + .../opengl/command-list/set-scissor-rects.md | 22 + .../opengl/command-list/set-stencil-ref.md | 20 + .../opengl/command-list/set-vertex-buffer.md | 23 + .../opengl/command-list/set-vertex-buffers.md | 24 + .../rhi/opengl/command-list/set-viewport.md | 24 + .../rhi/opengl/command-list/set-viewports.md | 22 + .../opengl/command-list/transition-barrier.md | 22 + .../rhi/opengl/command-queue/command-queue.md | 24 + .../command-queue/execute-command-lists.md | 22 + .../command-queue/get-completed-value.md | 19 + .../command-queue/get-timestamp-frequency.md | 19 + docs/api/rhi/opengl/command-queue/signal.md | 21 + .../rhi/opengl/command-queue/wait-for-idle.md | 17 + .../depth-stencil-view/bind-framebuffer.md | 20 + .../api/rhi/opengl/depth-stencil-view/bind.md | 11 + .../depth-stencil-view/clear-depth-stencil.md | 21 + .../opengl/depth-stencil-view/clear-depth.md | 20 + .../depth-stencil-view/clear-stencil.md | 20 + .../depth-stencil-view/depth-stencil-view.md | 29 + .../depth-stencil-view/get-framebuffer.md | 19 + .../depth-stencil-view/get-mip-level.md | 19 + .../rhi/opengl/depth-stencil-view/get-size.md | 14 + .../opengl/depth-stencil-view/get-texture.md | 19 + .../depth-stencil-view/initialize-cubemap.md | 25 + .../opengl/depth-stencil-view/initialize.md | 18 + .../rhi/opengl/depth-stencil-view/shutdown.md | 11 + .../depth-stencil-view/unbind-framebuffer.md | 17 + .../rhi/opengl/depth-stencil-view/unbind.md | 11 + .../rhi/opengl/device/create-render-window.md | 28 + docs/api/rhi/opengl/device/device.md | 37 + docs/api/rhi/opengl/device/get-window.md | 22 + .../device/initialize-with-existing-window.md | 26 + docs/api/rhi/opengl/device/poll-events.md | 23 + .../api/rhi/opengl/device/set-should-close.md | 20 + docs/api/rhi/opengl/device/should-close.md | 23 + docs/api/rhi/opengl/device/swap-buffers.md | 19 + docs/api/rhi/opengl/fence/fence.md | 25 + .../rhi/opengl/fence/get-completed-value.md | 19 + .../api/rhi/opengl/fence/get-current-value.md | 19 + docs/api/rhi/opengl/fence/get-status.md | 25 + docs/api/rhi/opengl/fence/initialize.md | 23 + docs/api/rhi/opengl/fence/is-signaled.md | 21 + docs/api/rhi/opengl/fence/reset.md | 17 + docs/api/rhi/opengl/fence/signal.md | 20 + docs/api/rhi/opengl/overview.md | 41 + .../rhi/opengl/pipeline-state/apply-blend.md | 21 + .../pipeline-state/apply-depth-stencil.md | 21 + .../opengl/pipeline-state/apply-rasterizer.md | 21 + .../opengl/pipeline-state/apply-scissor.md | 21 + .../opengl/pipeline-state/apply-viewport.md | 21 + docs/api/rhi/opengl/pipeline-state/apply.md | 27 + .../opengl/pipeline-state/attach-shader.md | 23 + .../opengl/pipeline-state/detach-shader.md | 20 + .../opengl/pipeline-state/get-blend-state.md | 25 + .../pipeline-state/get-depth-stencil-state.md | 25 + .../pipeline-state/get-rasterizer-state.md | 25 + .../opengl/pipeline-state/pipeline-state.md | 39 + .../opengl/pipeline-state/set-blend-state.md | 27 + .../opengl/pipeline-state/set-clear-color.md | 26 + .../pipeline-state/set-depth-stencil-state.md | 27 + .../pipeline-state/set-logical-operation.md | 25 + .../pipeline-state/set-rasterizer-state.md | 27 + .../rhi/opengl/pipeline-state/set-scissor.md | 29 + .../rhi/opengl/pipeline-state/set-viewport.md | 30 + .../render-target-view/bind-framebuffer.md | 20 + .../api/rhi/opengl/render-target-view/bind.md | 11 + .../rhi/opengl/render-target-view/clear.md | 17 + .../render-target-view/get-framebuffer.md | 19 + .../render-target-view/get-mip-level.md | 19 + .../rhi/opengl/render-target-view/get-size.md | 14 + .../opengl/render-target-view/get-texture.md | 19 + .../render-target-view/initialize-cubemap.md | 25 + .../opengl/render-target-view/initialize.md | 18 + .../render-target-view/render-target-view.md | 27 + .../rhi/opengl/render-target-view/shutdown.md | 11 + .../render-target-view/unbind-framebuffer.md | 17 + .../rhi/opengl/render-target-view/unbind.md | 11 + docs/api/rhi/opengl/sampler/bind.md | 22 + docs/api/rhi/opengl/sampler/get-id.md | 21 + docs/api/rhi/opengl/sampler/initialize.md | 29 + docs/api/rhi/opengl/sampler/sampler.md | 21 + docs/api/rhi/opengl/sampler/unbind.md | 22 + docs/api/rhi/opengl/shader/compile-compute.md | 30 + .../opengl/shader/compile-from-file-vs-fs.md | 25 + .../shader/compile-from-file-vs-gs-fs.md | 26 + docs/api/rhi/opengl/shader/compile-vs-fs.md | 34 + docs/api/rhi/opengl/shader/get-id.md | 23 + .../rhi/opengl/shader/get-uniform-location.md | 27 + docs/api/rhi/opengl/shader/set-float-array.md | 26 + docs/api/rhi/opengl/shader/set-int-array.md | 26 + docs/api/rhi/opengl/shader/shader.md | 33 + docs/api/rhi/opengl/shader/use.md | 21 + .../opengl/swap-chain/get-framebuffer-size.md | 23 + docs/api/rhi/opengl/swap-chain/get-size.md | 21 + docs/api/rhi/opengl/swap-chain/get-window.md | 22 + .../rhi/opengl/swap-chain/initialize-mode.md | 25 + docs/api/rhi/opengl/swap-chain/initialize.md | 24 + .../rhi/opengl/swap-chain/is-fullscreen.md | 24 + docs/api/rhi/opengl/swap-chain/is-vsync.md | 24 + docs/api/rhi/opengl/swap-chain/poll-events.md | 22 + docs/api/rhi/opengl/swap-chain/present.md | 24 + .../rhi/opengl/swap-chain/set-fullscreen.md | 23 + .../rhi/opengl/swap-chain/set-should-close.md | 23 + docs/api/rhi/opengl/swap-chain/set-vsync.md | 23 + .../api/rhi/opengl/swap-chain/should-close.md | 25 + .../api/rhi/opengl/swap-chain/swap-buffers.md | 20 + docs/api/rhi/opengl/swap-chain/swap-chain.md | 36 + docs/api/rhi/opengl/texture/bind-image.md | 22 + .../api/rhi/opengl/texture/generate-mipmap.md | 18 + docs/api/rhi/opengl/texture/get-id.md | 20 + .../api/rhi/opengl/texture/get-opengl-type.md | 23 + docs/api/rhi/opengl/texture/initialize-2d.md | 28 + .../rhi/opengl/texture/initialize-cube-map.md | 26 + docs/api/rhi/opengl/texture/load-from-file.md | 26 + docs/api/rhi/opengl/texture/set-filtering.md | 21 + docs/api/rhi/opengl/texture/set-wrapping.md | 22 + docs/api/rhi/opengl/texture/texture.md | 39 + .../opengl/vertex-array/add-vertex-buffer.md | 28 + docs/api/rhi/opengl/vertex-array/get-id.md | 20 + .../opengl/vertex-array/get-index-buffer.md | 19 + .../opengl/vertex-array/get-index-count.md | 20 + .../opengl/vertex-array/set-index-buffer.md | 21 + .../rhi/opengl/vertex-array/vertex-array.md | 23 + .../rhi/pipeline-layout/get-native-handle.md | 15 + docs/api/rhi/pipeline-layout/initialize.md | 18 + docs/api/rhi/pipeline-layout/methods.md | 25 + .../rhi/pipeline-layout/pipeline-layout.md | 20 + docs/api/rhi/pipeline-layout/shutdown.md | 13 + .../rhi/pipeline-state/get-native-handle.md | 15 + docs/api/rhi/pipeline-state/get-type.md | 15 + docs/api/rhi/pipeline-state/methods.md | 41 + docs/api/rhi/pipeline-state/pipeline-state.md | 30 + docs/api/rhi/pipeline-state/shutdown.md | 13 + docs/api/rhi/rhi.md | 121 + docs/api/rhi/sampler/get-id.md | 19 + docs/api/rhi/sampler/get-native-handle.md | 15 + docs/api/rhi/sampler/methods.md | 41 + docs/api/rhi/sampler/sampler.md | 22 + docs/api/rhi/sampler/shutdown.md | 13 + docs/api/rhi/shader/bind.md | 20 + docs/api/rhi/shader/compile-from-file.md | 26 + docs/api/rhi/shader/compile.md | 21 + docs/api/rhi/shader/get-native-handle.md | 15 + docs/api/rhi/shader/get-type.md | 15 + docs/api/rhi/shader/is-valid.md | 15 + docs/api/rhi/shader/set-float.md | 17 + docs/api/rhi/shader/set-int.md | 17 + docs/api/rhi/shader/set-mat4.md | 17 + docs/api/rhi/shader/set-vec3.md | 17 + docs/api/rhi/shader/set-vec4.md | 17 + docs/api/rhi/shader/shader.md | 55 + docs/api/rhi/shader/shutdown.md | 13 + docs/api/rhi/shader/unbind.md | 13 + .../get-current-back-buffer-index.md | 19 + .../rhi/swap-chain/get-current-back-buffer.md | 19 + docs/api/rhi/swap-chain/get-native-handle.md | 15 + docs/api/rhi/swap-chain/is-fullscreen.md | 21 + docs/api/rhi/swap-chain/methods.md | 89 + docs/api/rhi/swap-chain/poll-events.md | 17 + docs/api/rhi/swap-chain/present.md | 21 + docs/api/rhi/swap-chain/resize.md | 27 + docs/api/rhi/swap-chain/set-fullscreen.md | 20 + docs/api/rhi/swap-chain/set-should-close.md | 20 + docs/api/rhi/swap-chain/should-close.md | 21 + docs/api/rhi/swap-chain/shutdown.md | 13 + docs/api/rhi/swap-chain/swap-chain.md | 43 + docs/api/rhi/texture/get-depth.md | 15 + docs/api/rhi/texture/get-format.md | 15 + docs/api/rhi/texture/get-height.md | 15 + docs/api/rhi/texture/get-mip-levels.md | 15 + docs/api/rhi/texture/get-name.md | 20 + docs/api/rhi/texture/get-native-handle.md | 15 + docs/api/rhi/texture/get-state.md | 15 + docs/api/rhi/texture/get-texture-type.md | 15 + docs/api/rhi/texture/get-width.md | 15 + docs/api/rhi/texture/set-name.md | 22 + docs/api/rhi/texture/set-state.md | 22 + docs/api/rhi/texture/shutdown.md | 13 + docs/api/rhi/texture/texture.md | 80 + docs/api/rhi/types/types.md | 81 + docs/api/threading/lambdatask/constructor.md | 41 + docs/api/threading/lambdatask/lambdatask.md | 57 + docs/api/threading/mutex/lock.md | 34 + docs/api/threading/mutex/mutex.md | 54 + docs/api/threading/mutex/trylock.md | 36 + docs/api/threading/mutex/unlock.md | 32 + docs/api/threading/readwritelock/readlock.md | 36 + .../api/threading/readwritelock/readunlock.md | 33 + .../threading/readwritelock/readwritelock.md | 57 + docs/api/threading/readwritelock/writelock.md | 35 + .../threading/readwritelock/writeunlock.md | 32 + docs/api/threading/spinlock/lock.md | 35 + docs/api/threading/spinlock/spinlock.md | 53 + docs/api/threading/spinlock/trylock.md | 31 + docs/api/threading/spinlock/unlock.md | 32 + .../api/threading/task-group/adddependency.md | 44 + docs/api/threading/task-group/addtask.md | 60 + docs/api/threading/task-group/cancel.md | 45 + docs/api/threading/task-group/getprogress.md | 40 + docs/api/threading/task-group/iscomplete.md | 38 + .../task-group/setcompletecallback.md | 36 + docs/api/threading/task-group/task-group.md | 66 + docs/api/threading/task-group/wait.md | 46 + docs/api/threading/task-group/waitfor.md | 39 + .../threading/task-system/createtaskgroup.md | 39 + .../threading/task-system/destroytaskgroup.md | 32 + docs/api/threading/task-system/get.md | 26 + .../task-system/getworkerthreadcount.md | 25 + docs/api/threading/task-system/initialize.md | 37 + docs/api/threading/task-system/parallelfor.md | 46 + .../threading/task-system/runonmainthread.md | 43 + docs/api/threading/task-system/shutdown.md | 33 + docs/api/threading/task-system/submit.md | 63 + docs/api/threading/task-system/task-system.md | 82 + docs/api/threading/task-system/update.md | 36 + docs/api/threading/task-system/wait.md | 37 + docs/api/threading/task/addref.md | 27 + docs/api/threading/task/execute.md | 43 + docs/api/threading/task/getid.md | 25 + docs/api/threading/task/getpriority.md | 27 + docs/api/threading/task/getstatus.md | 32 + docs/api/threading/task/oncancel.md | 38 + docs/api/threading/task/oncomplete.md | 39 + docs/api/threading/task/release.md | 32 + docs/api/threading/task/setid.md | 28 + docs/api/threading/task/setpriority.md | 28 + docs/api/threading/task/setstatus.md | 35 + docs/api/threading/task/task.md | 88 + .../tasksystemconfig/enabletaskprofiling.md | 29 + .../tasksystemconfig/maxtaskqueuesize.md | 24 + .../threading/tasksystemconfig/stealtasks.md | 25 + .../tasksystemconfig/tasksystemconfig.md | 36 + .../tasksystemconfig/threadstacksize.md | 28 + .../tasksystemconfig/workerthreadcount.md | 25 + docs/api/threading/thread/detach.md | 38 + docs/api/threading/thread/getcurrentid.md | 30 + docs/api/threading/thread/getid.md | 30 + docs/api/threading/thread/getname.md | 28 + docs/api/threading/thread/join.md | 37 + docs/api/threading/thread/sleep.md | 30 + docs/api/threading/thread/start.md | 37 + docs/api/threading/thread/thread.md | 60 + docs/api/threading/thread/yield.md | 40 + docs/api/threading/threading.md | 74 + docs/plan/D3D12后端测试设计.md | 1612 +++++ docs/plan/OpenGL后端测试设计.md | 1186 ++++ docs/plan/OpenGL测试实施计划.md | 410 ++ docs/plan/RHI抽象层设计与实现.md | 1069 +++ docs/plan/TESTING.md | 285 + docs/plan/Unity SRP API参考文档.md | 621 ++ docs/plan/XCEngine渲染引擎架构设计.md | 4564 +++++++++++++ docs/plan/XCGameEngine架构设计.md | 6025 +++++++++++++++++ docs/plan/仿Unity RHI架构设计.md | 1325 ++++ .../DXR_Volumetric_Rendering_Research_Report.md | 297 + docs/plan/开题报告和任务书/任务书-王子文.docx | Bin 0 -> 17641 bytes docs/plan/开题报告和任务书/完整开题报告.md | 131 + .../plan/开题报告和任务书/开题报告-王子文.doc | 3 + docs/plan/旧版题目/开题报告-王子文.doc | 3 + docs/plan/旧版题目/开题报告-王子文.md | 180 + docs/plan/深入方向规划.md | 1309 ++++ docs/plan/第一阶段计划.md | 151 + docs/plan/第三阶段计划.md | 335 + docs/plan/第二阶段计划.md | 829 +++ docs/plan/第四阶段计划_资源系统.md | 5199 ++++++++++++++ electron/main.mjs | 4 +- src/components/ApiDocViewer.tsx | 53 +- src/components/DocContent.tsx | 23 +- src/components/DocTree.tsx | 16 +- 1012 files changed, 56880 insertions(+), 22 deletions(-) create mode 100644 .trae/documents/fix_doc_link_matching_plan.md create mode 100644 .trae/documents/fix_link_color_plan.md create mode 100644 .trae/documents/fix_link_navigation_plan.md create mode 100644 .trae/documents/hide_leaf_nodes_plan.md create mode 100644 docs/api/containers/array/array.md create mode 100644 docs/api/containers/array/clear.md create mode 100644 docs/api/containers/array/constructor.md create mode 100644 docs/api/containers/array/copy-move-constructor.md create mode 100644 docs/api/containers/array/data.md create mode 100644 docs/api/containers/array/destructor.md create mode 100644 docs/api/containers/array/emplaceback.md create mode 100644 docs/api/containers/array/front-back.md create mode 100644 docs/api/containers/array/iterator.md create mode 100644 docs/api/containers/array/operator-assign.md create mode 100644 docs/api/containers/array/operator-subscript.md create mode 100644 docs/api/containers/array/popback.md create mode 100644 docs/api/containers/array/pushback.md create mode 100644 docs/api/containers/array/reserve.md create mode 100644 docs/api/containers/array/resize.md create mode 100644 docs/api/containers/array/setallocator.md create mode 100644 docs/api/containers/array/size.md create mode 100644 docs/api/containers/containers.md create mode 100644 docs/api/containers/hashmap/clear.md create mode 100644 docs/api/containers/hashmap/constructor.md create mode 100644 docs/api/containers/hashmap/contains.md create mode 100644 docs/api/containers/hashmap/copy-move.md create mode 100644 docs/api/containers/hashmap/destructor.md create mode 100644 docs/api/containers/hashmap/erase.md create mode 100644 docs/api/containers/hashmap/find.md create mode 100644 docs/api/containers/hashmap/hashmap.md create mode 100644 docs/api/containers/hashmap/insert.md create mode 100644 docs/api/containers/hashmap/iterator.md create mode 100644 docs/api/containers/hashmap/operator-assign.md create mode 100644 docs/api/containers/hashmap/operator-subscript.md create mode 100644 docs/api/containers/hashmap/setallocator.md create mode 100644 docs/api/containers/hashmap/size.md create mode 100644 docs/api/containers/string/clear.md create mode 100644 docs/api/containers/string/constructor.md create mode 100644 docs/api/containers/string/cstr.md create mode 100644 docs/api/containers/string/destructor.md create mode 100644 docs/api/containers/string/ends-with.md create mode 100644 docs/api/containers/string/find.md create mode 100644 docs/api/containers/string/operator-assign.md create mode 100644 docs/api/containers/string/operator-equal.md create mode 100644 docs/api/containers/string/operator-plus-assign.md create mode 100644 docs/api/containers/string/operator-plus.md create mode 100644 docs/api/containers/string/operator-subscript.md create mode 100644 docs/api/containers/string/reserve-resize.md create mode 100644 docs/api/containers/string/size.md create mode 100644 docs/api/containers/string/starts-with.md create mode 100644 docs/api/containers/string/string.md create mode 100644 docs/api/containers/string/substring.md create mode 100644 docs/api/containers/string/to-lower-upper.md create mode 100644 docs/api/containers/string/trim.md create mode 100644 docs/api/core/core.md create mode 100644 docs/api/core/event/Clear.md create mode 100644 docs/api/core/event/Invoke.md create mode 100644 docs/api/core/event/ProcessUnsubscribes.md create mode 100644 docs/api/core/event/Subscribe.md create mode 100644 docs/api/core/event/Unsubscribe.md create mode 100644 docs/api/core/event/begin.md create mode 100644 docs/api/core/event/end.md create mode 100644 docs/api/core/event/event.md create mode 100644 docs/api/core/filewriter/Close.md create mode 100644 docs/api/core/filewriter/Flush.md create mode 100644 docs/api/core/filewriter/IsOpen.md create mode 100644 docs/api/core/filewriter/Open.md create mode 100644 docs/api/core/filewriter/Write.md create mode 100644 docs/api/core/filewriter/filewriter.md create mode 100644 docs/api/core/refcounted/AddRef.md create mode 100644 docs/api/core/refcounted/GetRefCount.md create mode 100644 docs/api/core/refcounted/Release.md create mode 100644 docs/api/core/refcounted/refcounted.md create mode 100644 docs/api/core/smartptr/MakeRef.md create mode 100644 docs/api/core/smartptr/MakeUnique.md create mode 100644 docs/api/core/smartptr/Ref.md create mode 100644 docs/api/core/smartptr/UniqueRef.md create mode 100644 docs/api/core/smartptr/smartptr.md create mode 100644 docs/api/core/types/byte.md create mode 100644 docs/api/core/types/int16.md create mode 100644 docs/api/core/types/int32.md create mode 100644 docs/api/core/types/int64.md create mode 100644 docs/api/core/types/int8.md create mode 100644 docs/api/core/types/types.md create mode 100644 docs/api/core/types/uint16.md create mode 100644 docs/api/core/types/uint32.md create mode 100644 docs/api/core/types/uint64.md create mode 100644 docs/api/core/types/uint8.md create mode 100644 docs/api/debug/consolelogsink/consolelogsink.md create mode 100644 docs/api/debug/consolelogsink/flush.md create mode 100644 docs/api/debug/consolelogsink/log.md create mode 100644 docs/api/debug/consolelogsink/overview.md create mode 100644 docs/api/debug/consolelogsink/setcoloroutput.md create mode 100644 docs/api/debug/consolelogsink/setminimumlevel.md create mode 100644 docs/api/debug/consolelogsink/~consolelogsink.md create mode 100644 docs/api/debug/debug.md create mode 100644 docs/api/debug/filelogsink/construct.md create mode 100644 docs/api/debug/filelogsink/filelogsink.md create mode 100644 docs/api/debug/filelogsink/flush.md create mode 100644 docs/api/debug/filelogsink/log.md create mode 100644 docs/api/debug/filelogsink/~filelogsink.md create mode 100644 docs/api/debug/ilogsink/flush.md create mode 100644 docs/api/debug/ilogsink/ilogsink.md create mode 100644 docs/api/debug/ilogsink/log.md create mode 100644 docs/api/debug/logcategory/logcategory.md create mode 100644 docs/api/debug/logcategory/logcategorytostring.md create mode 100644 docs/api/debug/logentry/logentry.md create mode 100644 docs/api/debug/logger/addsink.md create mode 100644 docs/api/debug/logger/debug.md create mode 100644 docs/api/debug/logger/error.md create mode 100644 docs/api/debug/logger/fatal.md create mode 100644 docs/api/debug/logger/get.md create mode 100644 docs/api/debug/logger/info.md create mode 100644 docs/api/debug/logger/initialize.md create mode 100644 docs/api/debug/logger/log.md create mode 100644 docs/api/debug/logger/logger.md create mode 100644 docs/api/debug/logger/removesink.md create mode 100644 docs/api/debug/logger/setcategoryenabled.md create mode 100644 docs/api/debug/logger/setminimumlevel.md create mode 100644 docs/api/debug/logger/shutdown.md create mode 100644 docs/api/debug/logger/verbose.md create mode 100644 docs/api/debug/logger/warning.md create mode 100644 docs/api/debug/loglevel/loglevel.md create mode 100644 docs/api/debug/loglevel/logleveltostring.md create mode 100644 docs/api/debug/profiler/beginframe.md create mode 100644 docs/api/debug/profiler/beginprofile.md create mode 100644 docs/api/debug/profiler/endframe.md create mode 100644 docs/api/debug/profiler/endprofile.md create mode 100644 docs/api/debug/profiler/exportchrometracing.md create mode 100644 docs/api/debug/profiler/get.md create mode 100644 docs/api/debug/profiler/initialize.md create mode 100644 docs/api/debug/profiler/markevent.md create mode 100644 docs/api/debug/profiler/profiler.md create mode 100644 docs/api/debug/profiler/setmarker.md create mode 100644 docs/api/debug/profiler/shutdown.md create mode 100644 docs/api/fix_links.py create mode 100644 docs/api/main.md create mode 100644 docs/api/math/aabb/aabb.md create mode 100644 docs/api/math/aabb/getaxis.md create mode 100644 docs/api/math/aabb/intersects-obb.md create mode 100644 docs/api/math/aabb/intersects-sphere.md create mode 100644 docs/api/math/aabb/obb-contains.md create mode 100644 docs/api/math/aabb/obb-getaxis.md create mode 100644 docs/api/math/aabb/obb-getmax.md create mode 100644 docs/api/math/aabb/obb-getmin.md create mode 100644 docs/api/math/aabb/obb-intersects-obb.md create mode 100644 docs/api/math/aabb/obb-intersects-sphere.md create mode 100644 docs/api/math/bounds/bounds.md create mode 100644 docs/api/math/bounds/contains.md create mode 100644 docs/api/math/bounds/encapsulate-bounds.md create mode 100644 docs/api/math/bounds/encapsulate.md create mode 100644 docs/api/math/bounds/expand.md create mode 100644 docs/api/math/bounds/getclosestpoint.md create mode 100644 docs/api/math/bounds/getmax.md create mode 100644 docs/api/math/bounds/getmin.md create mode 100644 docs/api/math/bounds/getvolume.md create mode 100644 docs/api/math/bounds/intersects.md create mode 100644 docs/api/math/bounds/setminmax.md create mode 100644 docs/api/math/box/box.md create mode 100644 docs/api/math/box/contains.md create mode 100644 docs/api/math/box/getmax.md create mode 100644 docs/api/math/box/getmin.md create mode 100644 docs/api/math/box/intersects-box.md create mode 100644 docs/api/math/box/intersects-ray.md create mode 100644 docs/api/math/box/intersects.md create mode 100644 docs/api/math/color/black.md create mode 100644 docs/api/math/color/blue.md create mode 100644 docs/api/math/color/clear.md create mode 100644 docs/api/math/color/color.md create mode 100644 docs/api/math/color/cyan.md create mode 100644 docs/api/math/color/green.md create mode 100644 docs/api/math/color/lerp.md create mode 100644 docs/api/math/color/magenta.md create mode 100644 docs/api/math/color/red.md create mode 100644 docs/api/math/color/torgba.md create mode 100644 docs/api/math/color/tovector3.md create mode 100644 docs/api/math/color/tovector4.md create mode 100644 docs/api/math/color/white.md create mode 100644 docs/api/math/color/yellow.md create mode 100644 docs/api/math/frustum/contains-bounds.md create mode 100644 docs/api/math/frustum/contains-point.md create mode 100644 docs/api/math/frustum/contains-sphere.md create mode 100644 docs/api/math/frustum/frustum.md create mode 100644 docs/api/math/frustum/intersects-bounds.md create mode 100644 docs/api/math/frustum/intersects-sphere.md create mode 100644 docs/api/math/h/deg-to-rad.md create mode 100644 docs/api/math/h/degrees.md create mode 100644 docs/api/math/h/epsilon.md create mode 100644 docs/api/math/h/float-max.md create mode 100644 docs/api/math/h/h.md create mode 100644 docs/api/math/h/half-pi.md create mode 100644 docs/api/math/h/pi.md create mode 100644 docs/api/math/h/rad-to-deg.md create mode 100644 docs/api/math/h/radians.md create mode 100644 docs/api/math/h/two-pi.md create mode 100644 docs/api/math/math.md create mode 100644 docs/api/math/matrix3/determinant.md create mode 100644 docs/api/math/matrix3/identity.md create mode 100644 docs/api/math/matrix3/inverse.md create mode 100644 docs/api/math/matrix3/matrix3.md create mode 100644 docs/api/math/matrix3/rotationx.md create mode 100644 docs/api/math/matrix3/rotationy.md create mode 100644 docs/api/math/matrix3/rotationz.md create mode 100644 docs/api/math/matrix3/scale.md create mode 100644 docs/api/math/matrix3/transpose.md create mode 100644 docs/api/math/matrix3/zero.md create mode 100644 docs/api/math/matrix4/decompose.md create mode 100644 docs/api/math/matrix4/determinant.md create mode 100644 docs/api/math/matrix4/getrotation.md create mode 100644 docs/api/math/matrix4/getscale.md create mode 100644 docs/api/math/matrix4/gettranslation.md create mode 100644 docs/api/math/matrix4/identity.md create mode 100644 docs/api/math/matrix4/inverse.md create mode 100644 docs/api/math/matrix4/lookat.md create mode 100644 docs/api/math/matrix4/matrix4.md create mode 100644 docs/api/math/matrix4/multiplypoint.md create mode 100644 docs/api/math/matrix4/multiplyvector.md create mode 100644 docs/api/math/matrix4/orthographic.md create mode 100644 docs/api/math/matrix4/perspective.md create mode 100644 docs/api/math/matrix4/rotation.md create mode 100644 docs/api/math/matrix4/rotationx.md create mode 100644 docs/api/math/matrix4/rotationy.md create mode 100644 docs/api/math/matrix4/rotationz.md create mode 100644 docs/api/math/matrix4/scale.md create mode 100644 docs/api/math/matrix4/translation.md create mode 100644 docs/api/math/matrix4/transpose.md create mode 100644 docs/api/math/matrix4/trs.md create mode 100644 docs/api/math/matrix4/zero.md create mode 100644 docs/api/math/plane/frompoints.md create mode 100644 docs/api/math/plane/getclosestpoint.md create mode 100644 docs/api/math/plane/getdistancetopoint.md create mode 100644 docs/api/math/plane/getside.md create mode 100644 docs/api/math/plane/intersects.md create mode 100644 docs/api/math/plane/plane.md create mode 100644 docs/api/math/quaternion/dot.md create mode 100644 docs/api/math/quaternion/fromaxisangle.md create mode 100644 docs/api/math/quaternion/fromeulerangles.md create mode 100644 docs/api/math/quaternion/fromrotationmatrix.md create mode 100644 docs/api/math/quaternion/identity.md create mode 100644 docs/api/math/quaternion/inverse.md create mode 100644 docs/api/math/quaternion/lookrotation.md create mode 100644 docs/api/math/quaternion/magnitude.md create mode 100644 docs/api/math/quaternion/normalized.md create mode 100644 docs/api/math/quaternion/quaternion-multiply.md create mode 100644 docs/api/math/quaternion/quaternion.md create mode 100644 docs/api/math/quaternion/slerp.md create mode 100644 docs/api/math/quaternion/toeulerangles.md create mode 100644 docs/api/math/quaternion/tomatrix4x4.md create mode 100644 docs/api/math/ray/getpoint.md create mode 100644 docs/api/math/ray/intersects-box.md create mode 100644 docs/api/math/ray/intersects-plane.md create mode 100644 docs/api/math/ray/intersects-sphere.md create mode 100644 docs/api/math/ray/ray.md create mode 100644 docs/api/math/rect/contains-float.md create mode 100644 docs/api/math/rect/contains-vector2.md create mode 100644 docs/api/math/rect/getbottom.md create mode 100644 docs/api/math/rect/getcenter.md create mode 100644 docs/api/math/rect/getleft.md create mode 100644 docs/api/math/rect/getposition.md create mode 100644 docs/api/math/rect/getright.md create mode 100644 docs/api/math/rect/getsize.md create mode 100644 docs/api/math/rect/gettop.md create mode 100644 docs/api/math/rect/intersect.md create mode 100644 docs/api/math/rect/intersects.md create mode 100644 docs/api/math/rect/rect-overview.md create mode 100644 docs/api/math/rect/rect.md create mode 100644 docs/api/math/rect/rectint-contains.md create mode 100644 docs/api/math/rect/rectint-getbottom.md create mode 100644 docs/api/math/rect/rectint-getcenter.md create mode 100644 docs/api/math/rect/rectint-getleft.md create mode 100644 docs/api/math/rect/rectint-getposition.md create mode 100644 docs/api/math/rect/rectint-getright.md create mode 100644 docs/api/math/rect/rectint-getsize.md create mode 100644 docs/api/math/rect/rectint-gettop.md create mode 100644 docs/api/math/rect/rectint-intersects.md create mode 100644 docs/api/math/rect/rectint.md create mode 100644 docs/api/math/rect/set.md create mode 100644 docs/api/math/rect/setposition-float.md create mode 100644 docs/api/math/rect/setposition-vector2.md create mode 100644 docs/api/math/rect/union.md create mode 100644 docs/api/math/rect/viewport-getaspectratio.md create mode 100644 docs/api/math/rect/viewport-getrect.md create mode 100644 docs/api/math/rect/viewport.md create mode 100644 docs/api/math/sphere/contains.md create mode 100644 docs/api/math/sphere/intersects.md create mode 100644 docs/api/math/sphere/sphere.md create mode 100644 docs/api/math/transform/inverse.md create mode 100644 docs/api/math/transform/inversetransformdirection.md create mode 100644 docs/api/math/transform/inversetransformpoint.md create mode 100644 docs/api/math/transform/tomatrix.md create mode 100644 docs/api/math/transform/transform.md create mode 100644 docs/api/math/transform/transformdirection.md create mode 100644 docs/api/math/transform/transformpoint.md create mode 100644 docs/api/math/vector2/cross.md create mode 100644 docs/api/math/vector2/dot.md create mode 100644 docs/api/math/vector2/down.md create mode 100644 docs/api/math/vector2/left.md create mode 100644 docs/api/math/vector2/lerp.md create mode 100644 docs/api/math/vector2/magnitude.md create mode 100644 docs/api/math/vector2/movetowards.md create mode 100644 docs/api/math/vector2/normalize.md create mode 100644 docs/api/math/vector2/normalized.md create mode 100644 docs/api/math/vector2/one.md create mode 100644 docs/api/math/vector2/right.md create mode 100644 docs/api/math/vector2/sqrmagnitude.md create mode 100644 docs/api/math/vector2/up.md create mode 100644 docs/api/math/vector2/vector2.md create mode 100644 docs/api/math/vector2/zero.md create mode 100644 docs/api/math/vector3/angle.md create mode 100644 docs/api/math/vector3/back.md create mode 100644 docs/api/math/vector3/cross.md create mode 100644 docs/api/math/vector3/dot.md create mode 100644 docs/api/math/vector3/down.md create mode 100644 docs/api/math/vector3/forward.md create mode 100644 docs/api/math/vector3/left.md create mode 100644 docs/api/math/vector3/lerp.md create mode 100644 docs/api/math/vector3/magnitude.md create mode 100644 docs/api/math/vector3/movetowards.md create mode 100644 docs/api/math/vector3/normalize.md create mode 100644 docs/api/math/vector3/normalized.md create mode 100644 docs/api/math/vector3/one.md create mode 100644 docs/api/math/vector3/project.md create mode 100644 docs/api/math/vector3/projectonplane.md create mode 100644 docs/api/math/vector3/quaternion-multiply.md create mode 100644 docs/api/math/vector3/reflect.md create mode 100644 docs/api/math/vector3/right.md create mode 100644 docs/api/math/vector3/sqrmagnitude.md create mode 100644 docs/api/math/vector3/up.md create mode 100644 docs/api/math/vector3/vector3.md create mode 100644 docs/api/math/vector3/zero.md create mode 100644 docs/api/math/vector4/dot.md create mode 100644 docs/api/math/vector4/one.md create mode 100644 docs/api/math/vector4/project.md create mode 100644 docs/api/math/vector4/tovector3.md create mode 100644 docs/api/math/vector4/vector4.md create mode 100644 docs/api/math/vector4/zero.md create mode 100644 docs/api/memory/allocator/allocate.md create mode 100644 docs/api/memory/allocator/allocator.md create mode 100644 docs/api/memory/allocator/free.md create mode 100644 docs/api/memory/allocator/get-allocation-count.md create mode 100644 docs/api/memory/allocator/get-name.md create mode 100644 docs/api/memory/allocator/get-peak-allocated.md create mode 100644 docs/api/memory/allocator/get-total-allocated.md create mode 100644 docs/api/memory/allocator/get-total-freed.md create mode 100644 docs/api/memory/allocator/reallocate.md create mode 100644 docs/api/memory/linear-allocator/allocate.md create mode 100644 docs/api/memory/linear-allocator/clear.md create mode 100644 docs/api/memory/linear-allocator/free.md create mode 100644 docs/api/memory/linear-allocator/get-capacity.md create mode 100644 docs/api/memory/linear-allocator/get-marker.md create mode 100644 docs/api/memory/linear-allocator/get-used-size.md create mode 100644 docs/api/memory/linear-allocator/linear-allocator.md create mode 100644 docs/api/memory/linear-allocator/reallocate.md create mode 100644 docs/api/memory/linear-allocator/set-marker.md create mode 100644 docs/api/memory/linear-allocator/~linear-allocator.md create mode 100644 docs/api/memory/manager/create-linear-allocator.md create mode 100644 docs/api/memory/manager/create-pool-allocator.md create mode 100644 docs/api/memory/manager/create-proxy-allocator.md create mode 100644 docs/api/memory/manager/dump-memory-leaks.md create mode 100644 docs/api/memory/manager/generate-memory-report.md create mode 100644 docs/api/memory/manager/get-system-allocator.md create mode 100644 docs/api/memory/manager/get.md create mode 100644 docs/api/memory/manager/initialize.md create mode 100644 docs/api/memory/manager/manager.md create mode 100644 docs/api/memory/manager/set-track-allocations.md create mode 100644 docs/api/memory/manager/shutdown.md create mode 100644 docs/api/memory/memory.md create mode 100644 docs/api/memory/pool-allocator/allocate.md create mode 100644 docs/api/memory/pool-allocator/contains.md create mode 100644 docs/api/memory/pool-allocator/free.md create mode 100644 docs/api/memory/pool-allocator/get-block-size.md create mode 100644 docs/api/memory/pool-allocator/get-free-block-count.md create mode 100644 docs/api/memory/pool-allocator/get-total-block-count.md create mode 100644 docs/api/memory/pool-allocator/pool-allocator.md create mode 100644 docs/api/memory/pool-allocator/reallocate.md create mode 100644 docs/api/memory/pool-allocator/~pool-allocator.md create mode 100644 docs/api/memory/proxy-allocator/allocate.md create mode 100644 docs/api/memory/proxy-allocator/free.md create mode 100644 docs/api/memory/proxy-allocator/get-stats.md create mode 100644 docs/api/memory/proxy-allocator/proxy-allocator.md create mode 100644 docs/api/memory/proxy-allocator/reallocate.md create mode 100644 docs/api/memory/proxy-allocator/~proxy-allocator.md create mode 100644 docs/api/resources/asyncloader/asyncloader.md create mode 100644 docs/api/resources/asyncloader/cancelall.md create mode 100644 docs/api/resources/asyncloader/getprogress.md create mode 100644 docs/api/resources/asyncloader/submit.md create mode 100644 docs/api/resources/asyncloader/update.md create mode 100644 docs/api/resources/audioclip/audioclip.md create mode 100644 docs/api/resources/audioclip/setaudiodata.md create mode 100644 docs/api/resources/dependencygraph/adddependency.md create mode 100644 docs/api/resources/dependencygraph/addnode.md create mode 100644 docs/api/resources/dependencygraph/dependencygraph.md create mode 100644 docs/api/resources/dependencygraph/getdependencies.md create mode 100644 docs/api/resources/dependencygraph/hascirculardependency.md create mode 100644 docs/api/resources/dependencygraph/topologicalsort.md create mode 100644 docs/api/resources/filearchive/filearchive.md create mode 100644 docs/api/resources/filesystem/exists.md create mode 100644 docs/api/resources/filesystem/filesystem.md create mode 100644 docs/api/resources/filesystem/initialize.md create mode 100644 docs/api/resources/filesystem/readresource.md create mode 100644 docs/api/resources/iloader/canload.md create mode 100644 docs/api/resources/iloader/getdefaultsettings.md create mode 100644 docs/api/resources/iloader/getsupportedextensions.md create mode 100644 docs/api/resources/iloader/iloader.md create mode 100644 docs/api/resources/iloader/load.md create mode 100644 docs/api/resources/iloader/loadasync.md create mode 100644 docs/api/resources/importsettings/importsettings.md create mode 100644 docs/api/resources/iresource/initialize.md create mode 100644 docs/api/resources/iresource/iresource.md create mode 100644 docs/api/resources/iresource/release.md create mode 100644 docs/api/resources/iresource/setinvalid.md create mode 100644 docs/api/resources/material/material.md create mode 100644 docs/api/resources/material/setfloat.md create mode 100644 docs/api/resources/material/setshader.md create mode 100644 docs/api/resources/material/settexture.md create mode 100644 docs/api/resources/material/updateconstantbuffer.md create mode 100644 docs/api/resources/mesh/addsection.md create mode 100644 docs/api/resources/mesh/mesh.md create mode 100644 docs/api/resources/mesh/setindexdata.md create mode 100644 docs/api/resources/mesh/setvertexdata.md create mode 100644 docs/api/resources/resourcecache/add.md create mode 100644 docs/api/resources/resourcecache/flush.md create mode 100644 docs/api/resources/resourcecache/getlrulist.md create mode 100644 docs/api/resources/resourcecache/onmemorypressure.md create mode 100644 docs/api/resources/resourcecache/resourcecache.md create mode 100644 docs/api/resources/resourcecache/touch.md create mode 100644 docs/api/resources/resourcehandle/get.md create mode 100644 docs/api/resources/resourcehandle/getguid.md create mode 100644 docs/api/resources/resourcehandle/isvalid.md create mode 100644 docs/api/resources/resourcehandle/reset.md create mode 100644 docs/api/resources/resourcehandle/resourcehandle.md create mode 100644 docs/api/resources/resourcehandle/swap.md create mode 100644 docs/api/resources/resourcemanager/exists.md create mode 100644 docs/api/resources/resourcemanager/find.md create mode 100644 docs/api/resources/resourcemanager/getloader.md create mode 100644 docs/api/resources/resourcemanager/load.md create mode 100644 docs/api/resources/resourcemanager/loadasync.md create mode 100644 docs/api/resources/resourcemanager/loadgroup.md create mode 100644 docs/api/resources/resourcemanager/registerloader.md create mode 100644 docs/api/resources/resourcemanager/resourcemanager.md create mode 100644 docs/api/resources/resourcemanager/setmemorybudget.md create mode 100644 docs/api/resources/resourcemanager/unload.md create mode 100644 docs/api/resources/resourcemanager/unloadunused.md create mode 100644 docs/api/resources/resourcepackage/resourcepackage.md create mode 100644 docs/api/resources/resourcepath/resourcepath.md create mode 100644 docs/api/resources/resources.md create mode 100644 docs/api/resources/resourcetypes/generate.md create mode 100644 docs/api/resources/resourcetypes/getresourcetypename.md create mode 100644 docs/api/resources/resourcetypes/resourcetypes.md create mode 100644 docs/api/resources/shader/addattribute.md create mode 100644 docs/api/resources/shader/adduniform.md create mode 100644 docs/api/resources/shader/shader.md create mode 100644 docs/api/resources/texture/create.md create mode 100644 docs/api/resources/texture/generatemipmaps.md create mode 100644 docs/api/resources/texture/texture.md create mode 100644 docs/api/rhi/buffer/buffer.md create mode 100644 docs/api/rhi/buffer/get-buffer-type.md create mode 100644 docs/api/rhi/buffer/get-name.md create mode 100644 docs/api/rhi/buffer/get-native-handle.md create mode 100644 docs/api/rhi/buffer/get-size.md create mode 100644 docs/api/rhi/buffer/get-state.md create mode 100644 docs/api/rhi/buffer/get-stride.md create mode 100644 docs/api/rhi/buffer/map.md create mode 100644 docs/api/rhi/buffer/set-buffer-type.md create mode 100644 docs/api/rhi/buffer/set-data.md create mode 100644 docs/api/rhi/buffer/set-name.md create mode 100644 docs/api/rhi/buffer/set-state.md create mode 100644 docs/api/rhi/buffer/set-stride.md create mode 100644 docs/api/rhi/buffer/shutdown.md create mode 100644 docs/api/rhi/buffer/unmap.md create mode 100644 docs/api/rhi/capabilities/capabilities.md create mode 100644 docs/api/rhi/command-list/clear-depth-stencil.md create mode 100644 docs/api/rhi/command-list/clear-render-target.md create mode 100644 docs/api/rhi/command-list/clear.md create mode 100644 docs/api/rhi/command-list/close.md create mode 100644 docs/api/rhi/command-list/command-list.md create mode 100644 docs/api/rhi/command-list/copy-resource.md create mode 100644 docs/api/rhi/command-list/dispatch.md create mode 100644 docs/api/rhi/command-list/draw-indexed.md create mode 100644 docs/api/rhi/command-list/draw.md create mode 100644 docs/api/rhi/command-list/methods.md create mode 100644 docs/api/rhi/command-list/reset.md create mode 100644 docs/api/rhi/command-list/set-blend-factor.md create mode 100644 docs/api/rhi/command-list/set-blend-state.md create mode 100644 docs/api/rhi/command-list/set-depth-stencil-state.md create mode 100644 docs/api/rhi/command-list/set-index-buffer.md create mode 100644 docs/api/rhi/command-list/set-pipeline-state.md create mode 100644 docs/api/rhi/command-list/set-primitive-topology.md create mode 100644 docs/api/rhi/command-list/set-render-targets.md create mode 100644 docs/api/rhi/command-list/set-scissor-rect.md create mode 100644 docs/api/rhi/command-list/set-scissor-rects.md create mode 100644 docs/api/rhi/command-list/set-stencil-ref.md create mode 100644 docs/api/rhi/command-list/set-vertex-buffer.md create mode 100644 docs/api/rhi/command-list/set-vertex-buffers.md create mode 100644 docs/api/rhi/command-list/set-viewport.md create mode 100644 docs/api/rhi/command-list/set-viewports.md create mode 100644 docs/api/rhi/command-list/shutdown.md create mode 100644 docs/api/rhi/command-list/transition-barrier.md create mode 100644 docs/api/rhi/command-queue/command-queue.md create mode 100644 docs/api/rhi/command-queue/execute-command-lists.md create mode 100644 docs/api/rhi/command-queue/get-completed-value.md create mode 100644 docs/api/rhi/command-queue/get-native-handle.md create mode 100644 docs/api/rhi/command-queue/get-timestamp-frequency.md create mode 100644 docs/api/rhi/command-queue/get-type.md create mode 100644 docs/api/rhi/command-queue/methods.md create mode 100644 docs/api/rhi/command-queue/shutdown.md create mode 100644 docs/api/rhi/command-queue/signal.md create mode 100644 docs/api/rhi/command-queue/wait-for-idle.md create mode 100644 docs/api/rhi/d3d12/buffer/buffer.md create mode 100644 docs/api/rhi/d3d12/buffer/get-buffer-type.md create mode 100644 docs/api/rhi/d3d12/buffer/get-desc.md create mode 100644 docs/api/rhi/d3d12/buffer/get-gpu-address.md create mode 100644 docs/api/rhi/d3d12/buffer/get-gpu-virtual-address.md create mode 100644 docs/api/rhi/d3d12/buffer/get-name.md create mode 100644 docs/api/rhi/d3d12/buffer/get-native-handle.md create mode 100644 docs/api/rhi/d3d12/buffer/get-resource.md create mode 100644 docs/api/rhi/d3d12/buffer/get-size.md create mode 100644 docs/api/rhi/d3d12/buffer/get-state.md create mode 100644 docs/api/rhi/d3d12/buffer/get-stride.md create mode 100644 docs/api/rhi/d3d12/buffer/initialize-from-existing.md create mode 100644 docs/api/rhi/d3d12/buffer/initialize-with-data.md create mode 100644 docs/api/rhi/d3d12/buffer/initialize.md create mode 100644 docs/api/rhi/d3d12/buffer/map.md create mode 100644 docs/api/rhi/d3d12/buffer/set-data.md create mode 100644 docs/api/rhi/d3d12/buffer/shutdown.md create mode 100644 docs/api/rhi/d3d12/buffer/unmap.md create mode 100644 docs/api/rhi/d3d12/buffer/update-data.md create mode 100644 docs/api/rhi/d3d12/command-allocator/command-allocator.md create mode 100644 docs/api/rhi/d3d12/command-allocator/get-command-allocator.md create mode 100644 docs/api/rhi/d3d12/command-allocator/is-ready.md create mode 100644 docs/api/rhi/d3d12/command-list/alias-barrier.md create mode 100644 docs/api/rhi/d3d12/command-list/begin-query.md create mode 100644 docs/api/rhi/d3d12/command-list/clear-depth-stencil.md create mode 100644 docs/api/rhi/d3d12/command-list/clear-render-target.md create mode 100644 docs/api/rhi/d3d12/command-list/command-list.md create mode 100644 docs/api/rhi/d3d12/command-list/copy-buffer.md create mode 100644 docs/api/rhi/d3d12/command-list/copy-resource.md create mode 100644 docs/api/rhi/d3d12/command-list/copy-texture.md create mode 100644 docs/api/rhi/d3d12/command-list/dispatch-indirect.md create mode 100644 docs/api/rhi/d3d12/command-list/dispatch.md create mode 100644 docs/api/rhi/d3d12/command-list/draw-indexed-instanced-indirect.md create mode 100644 docs/api/rhi/d3d12/command-list/draw-indexed.md create mode 100644 docs/api/rhi/d3d12/command-list/draw-instanced-indirect.md create mode 100644 docs/api/rhi/d3d12/command-list/draw.md create mode 100644 docs/api/rhi/d3d12/command-list/end-query.md create mode 100644 docs/api/rhi/d3d12/command-list/execute-bundle.md create mode 100644 docs/api/rhi/d3d12/command-list/get-command-list.md create mode 100644 docs/api/rhi/d3d12/command-list/get-resource-state.md create mode 100644 docs/api/rhi/d3d12/command-list/resolve-query-data.md create mode 100644 docs/api/rhi/d3d12/command-list/set-blend-factor.md create mode 100644 docs/api/rhi/d3d12/command-list/set-compute-descriptor-table.md create mode 100644 docs/api/rhi/d3d12/command-list/set-depth-bias.md create mode 100644 docs/api/rhi/d3d12/command-list/set-descriptor-heap.md create mode 100644 docs/api/rhi/d3d12/command-list/set-descriptor-heaps.md create mode 100644 docs/api/rhi/d3d12/command-list/set-graphics-descriptor-table.md create mode 100644 docs/api/rhi/d3d12/command-list/set-graphics-root-32bit-constants.md create mode 100644 docs/api/rhi/d3d12/command-list/set-graphics-root-constant-buffer-view.md create mode 100644 docs/api/rhi/d3d12/command-list/set-graphics-root-descriptor-table.md create mode 100644 docs/api/rhi/d3d12/command-list/set-graphics-root-shader-resource-view.md create mode 100644 docs/api/rhi/d3d12/command-list/set-index-buffer.md create mode 100644 docs/api/rhi/d3d12/command-list/set-pipeline-state.md create mode 100644 docs/api/rhi/d3d12/command-list/set-primitive-topology.md create mode 100644 docs/api/rhi/d3d12/command-list/set-render-targets-handle.md create mode 100644 docs/api/rhi/d3d12/command-list/set-render-targets-internal.md create mode 100644 docs/api/rhi/d3d12/command-list/set-render-targets.md create mode 100644 docs/api/rhi/d3d12/command-list/set-root-signature.md create mode 100644 docs/api/rhi/d3d12/command-list/set-scissor-rect.md create mode 100644 docs/api/rhi/d3d12/command-list/set-scissor-rects.md create mode 100644 docs/api/rhi/d3d12/command-list/set-stencil-ref.md create mode 100644 docs/api/rhi/d3d12/command-list/set-vertex-buffer.md create mode 100644 docs/api/rhi/d3d12/command-list/set-vertex-buffers.md create mode 100644 docs/api/rhi/d3d12/command-list/set-viewport.md create mode 100644 docs/api/rhi/d3d12/command-list/set-viewports.md create mode 100644 docs/api/rhi/d3d12/command-list/track-resource.md create mode 100644 docs/api/rhi/d3d12/command-list/transition-barrier-internal.md create mode 100644 docs/api/rhi/d3d12/command-list/transition-barrier.md create mode 100644 docs/api/rhi/d3d12/command-list/uav-barrier.md create mode 100644 docs/api/rhi/d3d12/command-queue/command-queue.md create mode 100644 docs/api/rhi/d3d12/command-queue/execute-command-lists.md create mode 100644 docs/api/rhi/d3d12/command-queue/get-command-queue.md create mode 100644 docs/api/rhi/d3d12/command-queue/get-completed-value.md create mode 100644 docs/api/rhi/d3d12/command-queue/get-timestamp-frequency.md create mode 100644 docs/api/rhi/d3d12/command-queue/signal.md create mode 100644 docs/api/rhi/d3d12/command-queue/wait-for-idle.md create mode 100644 docs/api/rhi/d3d12/common/common.md create mode 100644 docs/api/rhi/d3d12/constant-buffer-view/constant-buffer-view.md create mode 100644 docs/api/rhi/d3d12/constant-buffer-view/get-cpu-descriptor-handle.md create mode 100644 docs/api/rhi/d3d12/d3d12.md create mode 100644 docs/api/rhi/d3d12/depth-stencil-view/create-desc.md create mode 100644 docs/api/rhi/d3d12/depth-stencil-view/depth-stencil-view.md create mode 100644 docs/api/rhi/d3d12/depth-stencil-view/get-cpu-descriptor-handle.md create mode 100644 docs/api/rhi/d3d12/depth-stencil-view/initialize-at.md create mode 100644 docs/api/rhi/d3d12/descriptor-heap/create-desc.md create mode 100644 docs/api/rhi/d3d12/descriptor-heap/descriptor-heap.md create mode 100644 docs/api/rhi/d3d12/descriptor-heap/get-cpu-descriptor-handle-for-heap-start.md create mode 100644 docs/api/rhi/d3d12/descriptor-heap/get-cpu-descriptor-handle.md create mode 100644 docs/api/rhi/d3d12/descriptor-heap/get-descriptor-count.md create mode 100644 docs/api/rhi/d3d12/descriptor-heap/get-descriptor-heap.md create mode 100644 docs/api/rhi/d3d12/descriptor-heap/get-descriptor-size.md create mode 100644 docs/api/rhi/d3d12/descriptor-heap/get-gpu-descriptor-handle-for-heap-start.md create mode 100644 docs/api/rhi/d3d12/descriptor-heap/get-gpu-descriptor-handle.md create mode 100644 docs/api/rhi/d3d12/descriptor-heap/initialize-from-desc.md create mode 100644 docs/api/rhi/d3d12/device/check-feature-support.md create mode 100644 docs/api/rhi/d3d12/device/device.md create mode 100644 docs/api/rhi/d3d12/device/enumerate-adapters.md create mode 100644 docs/api/rhi/d3d12/device/get-adapter-info.md create mode 100644 docs/api/rhi/d3d12/device/get-descriptor-handle-increment-size.md create mode 100644 docs/api/rhi/d3d12/device/get-device.md create mode 100644 docs/api/rhi/d3d12/device/get-factory.md create mode 100644 docs/api/rhi/d3d12/device/methods.md create mode 100644 docs/api/rhi/d3d12/enums/enums.md create mode 100644 docs/api/rhi/d3d12/fence/fence.md create mode 100644 docs/api/rhi/d3d12/fence/get-completed-value.md create mode 100644 docs/api/rhi/d3d12/fence/get-event-handle.md create mode 100644 docs/api/rhi/d3d12/fence/get-fence.md create mode 100644 docs/api/rhi/d3d12/fence/is-signaled.md create mode 100644 docs/api/rhi/d3d12/fence/signal.md create mode 100644 docs/api/rhi/d3d12/pipeline-state/create-desc.md create mode 100644 docs/api/rhi/d3d12/pipeline-state/create-input-element.md create mode 100644 docs/api/rhi/d3d12/pipeline-state/get-pipeline-state.md create mode 100644 docs/api/rhi/d3d12/pipeline-state/pipeline-state.md create mode 100644 docs/api/rhi/d3d12/query-heap/get-count.md create mode 100644 docs/api/rhi/d3d12/query-heap/get-query-heap.md create mode 100644 docs/api/rhi/d3d12/query-heap/query-heap.md create mode 100644 docs/api/rhi/d3d12/render-target-view/create-desc.md create mode 100644 docs/api/rhi/d3d12/render-target-view/get-cpu-descriptor-handle.md create mode 100644 docs/api/rhi/d3d12/render-target-view/initialize-at.md create mode 100644 docs/api/rhi/d3d12/render-target-view/render-target-view.md create mode 100644 docs/api/rhi/d3d12/root-signature/create-32bit-constants.md create mode 100644 docs/api/rhi/d3d12/root-signature/create-cbv.md create mode 100644 docs/api/rhi/d3d12/root-signature/create-desc.md create mode 100644 docs/api/rhi/d3d12/root-signature/create-descriptor-range.md create mode 100644 docs/api/rhi/d3d12/root-signature/create-descriptor-table.md create mode 100644 docs/api/rhi/d3d12/root-signature/create-sampler-desc.md create mode 100644 docs/api/rhi/d3d12/root-signature/create-srv.md create mode 100644 docs/api/rhi/d3d12/root-signature/create-static-sampler.md create mode 100644 docs/api/rhi/d3d12/root-signature/create-uav.md create mode 100644 docs/api/rhi/d3d12/root-signature/get-parameter-count.md create mode 100644 docs/api/rhi/d3d12/root-signature/get-root-signature.md create mode 100644 docs/api/rhi/d3d12/root-signature/root-signature.md create mode 100644 docs/api/rhi/d3d12/sampler/get-id.md create mode 100644 docs/api/rhi/d3d12/sampler/sampler.md create mode 100644 docs/api/rhi/d3d12/screenshot/capture.md create mode 100644 docs/api/rhi/d3d12/screenshot/copy-to-readback-and-save.md create mode 100644 docs/api/rhi/d3d12/screenshot/screenshot.md create mode 100644 docs/api/rhi/d3d12/shader-resource-view/create-desc.md create mode 100644 docs/api/rhi/d3d12/shader-resource-view/get-cpu-descriptor-handle.md create mode 100644 docs/api/rhi/d3d12/shader-resource-view/initialize-at.md create mode 100644 docs/api/rhi/d3d12/shader-resource-view/shader-resource-view.md create mode 100644 docs/api/rhi/d3d12/shader/get-bytecode-size.md create mode 100644 docs/api/rhi/d3d12/shader/get-bytecode.md create mode 100644 docs/api/rhi/d3d12/shader/get-d3d12-bytecode.md create mode 100644 docs/api/rhi/d3d12/shader/get-input-layout.md create mode 100644 docs/api/rhi/d3d12/shader/set-uniforms.md create mode 100644 docs/api/rhi/d3d12/shader/shader.md create mode 100644 docs/api/rhi/d3d12/swap-chain/get-back-buffer.md create mode 100644 docs/api/rhi/d3d12/swap-chain/get-current-back-buffer-index.md create mode 100644 docs/api/rhi/d3d12/swap-chain/get-current-back-buffer.md create mode 100644 docs/api/rhi/d3d12/swap-chain/get-swap-chain.md create mode 100644 docs/api/rhi/d3d12/swap-chain/initialize-from-swapchain.md create mode 100644 docs/api/rhi/d3d12/swap-chain/is-fullscreen.md create mode 100644 docs/api/rhi/d3d12/swap-chain/poll-events.md create mode 100644 docs/api/rhi/d3d12/swap-chain/present.md create mode 100644 docs/api/rhi/d3d12/swap-chain/set-fullscreen.md create mode 100644 docs/api/rhi/d3d12/swap-chain/set-should-close.md create mode 100644 docs/api/rhi/d3d12/swap-chain/should-close.md create mode 100644 docs/api/rhi/d3d12/swap-chain/swap-chain.md create mode 100644 docs/api/rhi/d3d12/texture/get-array-size.md create mode 100644 docs/api/rhi/d3d12/texture/initialize-depth-stencil.md create mode 100644 docs/api/rhi/d3d12/texture/initialize-from-data.md create mode 100644 docs/api/rhi/d3d12/texture/texture.md create mode 100644 docs/api/rhi/d3d12/types/to-d3d12-buffer-desc.md create mode 100644 docs/api/rhi/d3d12/types/to-d3d12-clear-value.md create mode 100644 docs/api/rhi/d3d12/types/to-d3d12-command-queue-desc.md create mode 100644 docs/api/rhi/d3d12/types/to-d3d12-depth-stencil.md create mode 100644 docs/api/rhi/d3d12/types/to-d3d12-descriptor-heap-desc.md create mode 100644 docs/api/rhi/d3d12/types/to-d3d12-heap-properties.md create mode 100644 docs/api/rhi/d3d12/types/to-d3d12-rect.md create mode 100644 docs/api/rhi/d3d12/types/to-d3d12-texture-desc.md create mode 100644 docs/api/rhi/d3d12/types/to-d3d12-viewport.md create mode 100644 docs/api/rhi/d3d12/types/types.md create mode 100644 docs/api/rhi/d3d12/unordered-access-view/get-cpu-descriptor-handle.md create mode 100644 docs/api/rhi/d3d12/unordered-access-view/unordered-access-view.md create mode 100644 docs/api/rhi/descriptor-pool/descriptor-pool.md create mode 100644 docs/api/rhi/descriptor-pool/get-descriptor-count.md create mode 100644 docs/api/rhi/descriptor-pool/methods.md create mode 100644 docs/api/rhi/device/compile-shader.md create mode 100644 docs/api/rhi/device/create-buffer.md create mode 100644 docs/api/rhi/device/create-command-list.md create mode 100644 docs/api/rhi/device/create-command-queue.md create mode 100644 docs/api/rhi/device/create-fence.md create mode 100644 docs/api/rhi/device/create-pipeline-state.md create mode 100644 docs/api/rhi/device/create-sampler.md create mode 100644 docs/api/rhi/device/create-swap-chain.md create mode 100644 docs/api/rhi/device/create-texture.md create mode 100644 docs/api/rhi/device/device.md create mode 100644 docs/api/rhi/device/get-capabilities.md create mode 100644 docs/api/rhi/device/get-device-info.md create mode 100644 docs/api/rhi/device/get-native-device.md create mode 100644 docs/api/rhi/device/initialize.md create mode 100644 docs/api/rhi/device/shutdown.md create mode 100644 docs/api/rhi/enums/enums.md create mode 100644 docs/api/rhi/factory/create-rhi-device-string.md create mode 100644 docs/api/rhi/factory/create-rhi-device-type.md create mode 100644 docs/api/rhi/factory/factory.md create mode 100644 docs/api/rhi/fence/fence.md create mode 100644 docs/api/rhi/fence/get-completed-value.md create mode 100644 docs/api/rhi/fence/get-native-handle.md create mode 100644 docs/api/rhi/fence/is-signaled.md create mode 100644 docs/api/rhi/fence/methods.md create mode 100644 docs/api/rhi/fence/shutdown.md create mode 100644 docs/api/rhi/fence/signal.md create mode 100644 docs/api/rhi/fence/wait.md create mode 100644 docs/api/rhi/opengl/README.md create mode 100644 docs/api/rhi/opengl/buffer/bind-base.md create mode 100644 docs/api/rhi/opengl/buffer/bind.md create mode 100644 docs/api/rhi/opengl/buffer/buffer.md create mode 100644 docs/api/rhi/opengl/buffer/get-id.md create mode 100644 docs/api/rhi/opengl/buffer/get-type.md create mode 100644 docs/api/rhi/opengl/buffer/initialize-index-buffer.md create mode 100644 docs/api/rhi/opengl/buffer/initialize-vertex-buffer.md create mode 100644 docs/api/rhi/opengl/buffer/initialize.md create mode 100644 docs/api/rhi/opengl/buffer/is-dynamic.md create mode 100644 docs/api/rhi/opengl/buffer/unbind.md create mode 100644 docs/api/rhi/opengl/command-list/clear-color.md create mode 100644 docs/api/rhi/opengl/command-list/clear-depth-stencil.md create mode 100644 docs/api/rhi/opengl/command-list/clear-depth.md create mode 100644 docs/api/rhi/opengl/command-list/clear-render-target.md create mode 100644 docs/api/rhi/opengl/command-list/clear-stencil.md create mode 100644 docs/api/rhi/opengl/command-list/clear.md create mode 100644 docs/api/rhi/opengl/command-list/command-list.md create mode 100644 docs/api/rhi/opengl/command-list/copy-resource.md create mode 100644 docs/api/rhi/opengl/command-list/dispatch.md create mode 100644 docs/api/rhi/opengl/command-list/draw-indexed.md create mode 100644 docs/api/rhi/opengl/command-list/draw.md create mode 100644 docs/api/rhi/opengl/command-list/opengl-methods.md create mode 100644 docs/api/rhi/opengl/command-list/set-blend-factor.md create mode 100644 docs/api/rhi/opengl/command-list/set-blend-state.md create mode 100644 docs/api/rhi/opengl/command-list/set-depth-stencil-state.md create mode 100644 docs/api/rhi/opengl/command-list/set-index-buffer.md create mode 100644 docs/api/rhi/opengl/command-list/set-pipeline-state.md create mode 100644 docs/api/rhi/opengl/command-list/set-primitive-topology.md create mode 100644 docs/api/rhi/opengl/command-list/set-render-targets.md create mode 100644 docs/api/rhi/opengl/command-list/set-scissor-rect.md create mode 100644 docs/api/rhi/opengl/command-list/set-scissor-rects.md create mode 100644 docs/api/rhi/opengl/command-list/set-stencil-ref.md create mode 100644 docs/api/rhi/opengl/command-list/set-vertex-buffer.md create mode 100644 docs/api/rhi/opengl/command-list/set-vertex-buffers.md create mode 100644 docs/api/rhi/opengl/command-list/set-viewport.md create mode 100644 docs/api/rhi/opengl/command-list/set-viewports.md create mode 100644 docs/api/rhi/opengl/command-list/transition-barrier.md create mode 100644 docs/api/rhi/opengl/command-queue/command-queue.md create mode 100644 docs/api/rhi/opengl/command-queue/execute-command-lists.md create mode 100644 docs/api/rhi/opengl/command-queue/get-completed-value.md create mode 100644 docs/api/rhi/opengl/command-queue/get-timestamp-frequency.md create mode 100644 docs/api/rhi/opengl/command-queue/signal.md create mode 100644 docs/api/rhi/opengl/command-queue/wait-for-idle.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/bind-framebuffer.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/bind.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/clear-depth-stencil.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/clear-depth.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/clear-stencil.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/depth-stencil-view.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/get-framebuffer.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/get-mip-level.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/get-size.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/get-texture.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/initialize-cubemap.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/initialize.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/shutdown.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/unbind-framebuffer.md create mode 100644 docs/api/rhi/opengl/depth-stencil-view/unbind.md create mode 100644 docs/api/rhi/opengl/device/create-render-window.md create mode 100644 docs/api/rhi/opengl/device/device.md create mode 100644 docs/api/rhi/opengl/device/get-window.md create mode 100644 docs/api/rhi/opengl/device/initialize-with-existing-window.md create mode 100644 docs/api/rhi/opengl/device/poll-events.md create mode 100644 docs/api/rhi/opengl/device/set-should-close.md create mode 100644 docs/api/rhi/opengl/device/should-close.md create mode 100644 docs/api/rhi/opengl/device/swap-buffers.md create mode 100644 docs/api/rhi/opengl/fence/fence.md create mode 100644 docs/api/rhi/opengl/fence/get-completed-value.md create mode 100644 docs/api/rhi/opengl/fence/get-current-value.md create mode 100644 docs/api/rhi/opengl/fence/get-status.md create mode 100644 docs/api/rhi/opengl/fence/initialize.md create mode 100644 docs/api/rhi/opengl/fence/is-signaled.md create mode 100644 docs/api/rhi/opengl/fence/reset.md create mode 100644 docs/api/rhi/opengl/fence/signal.md create mode 100644 docs/api/rhi/opengl/overview.md create mode 100644 docs/api/rhi/opengl/pipeline-state/apply-blend.md create mode 100644 docs/api/rhi/opengl/pipeline-state/apply-depth-stencil.md create mode 100644 docs/api/rhi/opengl/pipeline-state/apply-rasterizer.md create mode 100644 docs/api/rhi/opengl/pipeline-state/apply-scissor.md create mode 100644 docs/api/rhi/opengl/pipeline-state/apply-viewport.md create mode 100644 docs/api/rhi/opengl/pipeline-state/apply.md create mode 100644 docs/api/rhi/opengl/pipeline-state/attach-shader.md create mode 100644 docs/api/rhi/opengl/pipeline-state/detach-shader.md create mode 100644 docs/api/rhi/opengl/pipeline-state/get-blend-state.md create mode 100644 docs/api/rhi/opengl/pipeline-state/get-depth-stencil-state.md create mode 100644 docs/api/rhi/opengl/pipeline-state/get-rasterizer-state.md create mode 100644 docs/api/rhi/opengl/pipeline-state/pipeline-state.md create mode 100644 docs/api/rhi/opengl/pipeline-state/set-blend-state.md create mode 100644 docs/api/rhi/opengl/pipeline-state/set-clear-color.md create mode 100644 docs/api/rhi/opengl/pipeline-state/set-depth-stencil-state.md create mode 100644 docs/api/rhi/opengl/pipeline-state/set-logical-operation.md create mode 100644 docs/api/rhi/opengl/pipeline-state/set-rasterizer-state.md create mode 100644 docs/api/rhi/opengl/pipeline-state/set-scissor.md create mode 100644 docs/api/rhi/opengl/pipeline-state/set-viewport.md create mode 100644 docs/api/rhi/opengl/render-target-view/bind-framebuffer.md create mode 100644 docs/api/rhi/opengl/render-target-view/bind.md create mode 100644 docs/api/rhi/opengl/render-target-view/clear.md create mode 100644 docs/api/rhi/opengl/render-target-view/get-framebuffer.md create mode 100644 docs/api/rhi/opengl/render-target-view/get-mip-level.md create mode 100644 docs/api/rhi/opengl/render-target-view/get-size.md create mode 100644 docs/api/rhi/opengl/render-target-view/get-texture.md create mode 100644 docs/api/rhi/opengl/render-target-view/initialize-cubemap.md create mode 100644 docs/api/rhi/opengl/render-target-view/initialize.md create mode 100644 docs/api/rhi/opengl/render-target-view/render-target-view.md create mode 100644 docs/api/rhi/opengl/render-target-view/shutdown.md create mode 100644 docs/api/rhi/opengl/render-target-view/unbind-framebuffer.md create mode 100644 docs/api/rhi/opengl/render-target-view/unbind.md create mode 100644 docs/api/rhi/opengl/sampler/bind.md create mode 100644 docs/api/rhi/opengl/sampler/get-id.md create mode 100644 docs/api/rhi/opengl/sampler/initialize.md create mode 100644 docs/api/rhi/opengl/sampler/sampler.md create mode 100644 docs/api/rhi/opengl/sampler/unbind.md create mode 100644 docs/api/rhi/opengl/shader/compile-compute.md create mode 100644 docs/api/rhi/opengl/shader/compile-from-file-vs-fs.md create mode 100644 docs/api/rhi/opengl/shader/compile-from-file-vs-gs-fs.md create mode 100644 docs/api/rhi/opengl/shader/compile-vs-fs.md create mode 100644 docs/api/rhi/opengl/shader/get-id.md create mode 100644 docs/api/rhi/opengl/shader/get-uniform-location.md create mode 100644 docs/api/rhi/opengl/shader/set-float-array.md create mode 100644 docs/api/rhi/opengl/shader/set-int-array.md create mode 100644 docs/api/rhi/opengl/shader/shader.md create mode 100644 docs/api/rhi/opengl/shader/use.md create mode 100644 docs/api/rhi/opengl/swap-chain/get-framebuffer-size.md create mode 100644 docs/api/rhi/opengl/swap-chain/get-size.md create mode 100644 docs/api/rhi/opengl/swap-chain/get-window.md create mode 100644 docs/api/rhi/opengl/swap-chain/initialize-mode.md create mode 100644 docs/api/rhi/opengl/swap-chain/initialize.md create mode 100644 docs/api/rhi/opengl/swap-chain/is-fullscreen.md create mode 100644 docs/api/rhi/opengl/swap-chain/is-vsync.md create mode 100644 docs/api/rhi/opengl/swap-chain/poll-events.md create mode 100644 docs/api/rhi/opengl/swap-chain/present.md create mode 100644 docs/api/rhi/opengl/swap-chain/set-fullscreen.md create mode 100644 docs/api/rhi/opengl/swap-chain/set-should-close.md create mode 100644 docs/api/rhi/opengl/swap-chain/set-vsync.md create mode 100644 docs/api/rhi/opengl/swap-chain/should-close.md create mode 100644 docs/api/rhi/opengl/swap-chain/swap-buffers.md create mode 100644 docs/api/rhi/opengl/swap-chain/swap-chain.md create mode 100644 docs/api/rhi/opengl/texture/bind-image.md create mode 100644 docs/api/rhi/opengl/texture/generate-mipmap.md create mode 100644 docs/api/rhi/opengl/texture/get-id.md create mode 100644 docs/api/rhi/opengl/texture/get-opengl-type.md create mode 100644 docs/api/rhi/opengl/texture/initialize-2d.md create mode 100644 docs/api/rhi/opengl/texture/initialize-cube-map.md create mode 100644 docs/api/rhi/opengl/texture/load-from-file.md create mode 100644 docs/api/rhi/opengl/texture/set-filtering.md create mode 100644 docs/api/rhi/opengl/texture/set-wrapping.md create mode 100644 docs/api/rhi/opengl/texture/texture.md create mode 100644 docs/api/rhi/opengl/vertex-array/add-vertex-buffer.md create mode 100644 docs/api/rhi/opengl/vertex-array/get-id.md create mode 100644 docs/api/rhi/opengl/vertex-array/get-index-buffer.md create mode 100644 docs/api/rhi/opengl/vertex-array/get-index-count.md create mode 100644 docs/api/rhi/opengl/vertex-array/set-index-buffer.md create mode 100644 docs/api/rhi/opengl/vertex-array/vertex-array.md create mode 100644 docs/api/rhi/pipeline-layout/get-native-handle.md create mode 100644 docs/api/rhi/pipeline-layout/initialize.md create mode 100644 docs/api/rhi/pipeline-layout/methods.md create mode 100644 docs/api/rhi/pipeline-layout/pipeline-layout.md create mode 100644 docs/api/rhi/pipeline-layout/shutdown.md create mode 100644 docs/api/rhi/pipeline-state/get-native-handle.md create mode 100644 docs/api/rhi/pipeline-state/get-type.md create mode 100644 docs/api/rhi/pipeline-state/methods.md create mode 100644 docs/api/rhi/pipeline-state/pipeline-state.md create mode 100644 docs/api/rhi/pipeline-state/shutdown.md create mode 100644 docs/api/rhi/rhi.md create mode 100644 docs/api/rhi/sampler/get-id.md create mode 100644 docs/api/rhi/sampler/get-native-handle.md create mode 100644 docs/api/rhi/sampler/methods.md create mode 100644 docs/api/rhi/sampler/sampler.md create mode 100644 docs/api/rhi/sampler/shutdown.md create mode 100644 docs/api/rhi/shader/bind.md create mode 100644 docs/api/rhi/shader/compile-from-file.md create mode 100644 docs/api/rhi/shader/compile.md create mode 100644 docs/api/rhi/shader/get-native-handle.md create mode 100644 docs/api/rhi/shader/get-type.md create mode 100644 docs/api/rhi/shader/is-valid.md create mode 100644 docs/api/rhi/shader/set-float.md create mode 100644 docs/api/rhi/shader/set-int.md create mode 100644 docs/api/rhi/shader/set-mat4.md create mode 100644 docs/api/rhi/shader/set-vec3.md create mode 100644 docs/api/rhi/shader/set-vec4.md create mode 100644 docs/api/rhi/shader/shader.md create mode 100644 docs/api/rhi/shader/shutdown.md create mode 100644 docs/api/rhi/shader/unbind.md create mode 100644 docs/api/rhi/swap-chain/get-current-back-buffer-index.md create mode 100644 docs/api/rhi/swap-chain/get-current-back-buffer.md create mode 100644 docs/api/rhi/swap-chain/get-native-handle.md create mode 100644 docs/api/rhi/swap-chain/is-fullscreen.md create mode 100644 docs/api/rhi/swap-chain/methods.md create mode 100644 docs/api/rhi/swap-chain/poll-events.md create mode 100644 docs/api/rhi/swap-chain/present.md create mode 100644 docs/api/rhi/swap-chain/resize.md create mode 100644 docs/api/rhi/swap-chain/set-fullscreen.md create mode 100644 docs/api/rhi/swap-chain/set-should-close.md create mode 100644 docs/api/rhi/swap-chain/should-close.md create mode 100644 docs/api/rhi/swap-chain/shutdown.md create mode 100644 docs/api/rhi/swap-chain/swap-chain.md create mode 100644 docs/api/rhi/texture/get-depth.md create mode 100644 docs/api/rhi/texture/get-format.md create mode 100644 docs/api/rhi/texture/get-height.md create mode 100644 docs/api/rhi/texture/get-mip-levels.md create mode 100644 docs/api/rhi/texture/get-name.md create mode 100644 docs/api/rhi/texture/get-native-handle.md create mode 100644 docs/api/rhi/texture/get-state.md create mode 100644 docs/api/rhi/texture/get-texture-type.md create mode 100644 docs/api/rhi/texture/get-width.md create mode 100644 docs/api/rhi/texture/set-name.md create mode 100644 docs/api/rhi/texture/set-state.md create mode 100644 docs/api/rhi/texture/shutdown.md create mode 100644 docs/api/rhi/texture/texture.md create mode 100644 docs/api/rhi/types/types.md create mode 100644 docs/api/threading/lambdatask/constructor.md create mode 100644 docs/api/threading/lambdatask/lambdatask.md create mode 100644 docs/api/threading/mutex/lock.md create mode 100644 docs/api/threading/mutex/mutex.md create mode 100644 docs/api/threading/mutex/trylock.md create mode 100644 docs/api/threading/mutex/unlock.md create mode 100644 docs/api/threading/readwritelock/readlock.md create mode 100644 docs/api/threading/readwritelock/readunlock.md create mode 100644 docs/api/threading/readwritelock/readwritelock.md create mode 100644 docs/api/threading/readwritelock/writelock.md create mode 100644 docs/api/threading/readwritelock/writeunlock.md create mode 100644 docs/api/threading/spinlock/lock.md create mode 100644 docs/api/threading/spinlock/spinlock.md create mode 100644 docs/api/threading/spinlock/trylock.md create mode 100644 docs/api/threading/spinlock/unlock.md create mode 100644 docs/api/threading/task-group/adddependency.md create mode 100644 docs/api/threading/task-group/addtask.md create mode 100644 docs/api/threading/task-group/cancel.md create mode 100644 docs/api/threading/task-group/getprogress.md create mode 100644 docs/api/threading/task-group/iscomplete.md create mode 100644 docs/api/threading/task-group/setcompletecallback.md create mode 100644 docs/api/threading/task-group/task-group.md create mode 100644 docs/api/threading/task-group/wait.md create mode 100644 docs/api/threading/task-group/waitfor.md create mode 100644 docs/api/threading/task-system/createtaskgroup.md create mode 100644 docs/api/threading/task-system/destroytaskgroup.md create mode 100644 docs/api/threading/task-system/get.md create mode 100644 docs/api/threading/task-system/getworkerthreadcount.md create mode 100644 docs/api/threading/task-system/initialize.md create mode 100644 docs/api/threading/task-system/parallelfor.md create mode 100644 docs/api/threading/task-system/runonmainthread.md create mode 100644 docs/api/threading/task-system/shutdown.md create mode 100644 docs/api/threading/task-system/submit.md create mode 100644 docs/api/threading/task-system/task-system.md create mode 100644 docs/api/threading/task-system/update.md create mode 100644 docs/api/threading/task-system/wait.md create mode 100644 docs/api/threading/task/addref.md create mode 100644 docs/api/threading/task/execute.md create mode 100644 docs/api/threading/task/getid.md create mode 100644 docs/api/threading/task/getpriority.md create mode 100644 docs/api/threading/task/getstatus.md create mode 100644 docs/api/threading/task/oncancel.md create mode 100644 docs/api/threading/task/oncomplete.md create mode 100644 docs/api/threading/task/release.md create mode 100644 docs/api/threading/task/setid.md create mode 100644 docs/api/threading/task/setpriority.md create mode 100644 docs/api/threading/task/setstatus.md create mode 100644 docs/api/threading/task/task.md create mode 100644 docs/api/threading/tasksystemconfig/enabletaskprofiling.md create mode 100644 docs/api/threading/tasksystemconfig/maxtaskqueuesize.md create mode 100644 docs/api/threading/tasksystemconfig/stealtasks.md create mode 100644 docs/api/threading/tasksystemconfig/tasksystemconfig.md create mode 100644 docs/api/threading/tasksystemconfig/threadstacksize.md create mode 100644 docs/api/threading/tasksystemconfig/workerthreadcount.md create mode 100644 docs/api/threading/thread/detach.md create mode 100644 docs/api/threading/thread/getcurrentid.md create mode 100644 docs/api/threading/thread/getid.md create mode 100644 docs/api/threading/thread/getname.md create mode 100644 docs/api/threading/thread/join.md create mode 100644 docs/api/threading/thread/sleep.md create mode 100644 docs/api/threading/thread/start.md create mode 100644 docs/api/threading/thread/thread.md create mode 100644 docs/api/threading/thread/yield.md create mode 100644 docs/api/threading/threading.md create mode 100644 docs/plan/D3D12后端测试设计.md create mode 100644 docs/plan/OpenGL后端测试设计.md create mode 100644 docs/plan/OpenGL测试实施计划.md create mode 100644 docs/plan/RHI抽象层设计与实现.md create mode 100644 docs/plan/TESTING.md create mode 100644 docs/plan/Unity SRP API参考文档.md create mode 100644 docs/plan/XCEngine渲染引擎架构设计.md create mode 100644 docs/plan/XCGameEngine架构设计.md create mode 100644 docs/plan/仿Unity RHI架构设计.md create mode 100644 docs/plan/开题报告和任务书/DXR_Volumetric_Rendering_Research_Report.md create mode 100644 docs/plan/开题报告和任务书/任务书-王子文.docx create mode 100644 docs/plan/开题报告和任务书/完整开题报告.md create mode 100644 docs/plan/开题报告和任务书/开题报告-王子文.doc create mode 100644 docs/plan/旧版题目/开题报告-王子文.doc create mode 100644 docs/plan/旧版题目/开题报告-王子文.md create mode 100644 docs/plan/深入方向规划.md create mode 100644 docs/plan/第一阶段计划.md create mode 100644 docs/plan/第三阶段计划.md create mode 100644 docs/plan/第二阶段计划.md create mode 100644 docs/plan/第四阶段计划_资源系统.md diff --git a/.trae/documents/fix_doc_link_matching_plan.md b/.trae/documents/fix_doc_link_matching_plan.md new file mode 100644 index 0000000..027f524 --- /dev/null +++ b/.trae/documents/fix_doc_link_matching_plan.md @@ -0,0 +1,82 @@ +# 修复文档链接匹配逻辑计划 + +## 1. 问题分析 +用户反馈点击 `rhi/buffer/d3d12/buffer.md` 中的 `[Initialize](initialize.md)` 链接时,错误跳转到了 `Logger::Initialize`(可能位于其他目录)。 +经过检查 `src/components/ApiDocViewer.tsx` 中的 `handleReferenceClick` 方法: + +```typescript + const handleReferenceClick = useCallback((href: string) => { + const ref = href.replace(/\.md$/, '') + const match = externalDocs.find(d => { + const docPath = d.relativePath.replace(/\.md$/, '') + return docPath === ref || docPath.endsWith('/' + ref.split('/').pop()) + }) + if (match) { + setSelectedPath(match.relativePath) + setCurrentContent(match.content) + } + }, [externalDocs]) +``` + +当前的匹配逻辑非常危险:`docPath.endsWith('/' + ref.split('/').pop())` 这一行意味着只要文件名匹配(例如 `initialize.md`),不管它在哪个目录下,都可能被匹配到。这导致了跨目录的同名文件匹配错误。 + +## 2. 修复方案 + +### 修改文件: `src/components/ApiDocViewer.tsx` + +我们需要实现基于当前文档路径的相对路径解析逻辑。由于 `handleReferenceClick` 目前只接收 `href`,我们需要让它知道当前所在的文档路径(`selectedPath`),以便正确解析相对路径。 + +1. **依赖当前路径**:确保 `handleReferenceClick` 能访问到 `selectedPath`。 +2. **实现相对路径解析**: + - 如果链接以 `/` 开头,视为基于文档根目录的绝对路径。 + - 如果是相对路径(`./`、`../` 或直接文件名),则基于当前文档的目录进行解析。 + - 解析出目标文件的完整 `relativePath` 后,再在 `externalDocs` 中查找精确匹配。 + +**修改后的逻辑伪代码**: +```typescript + const handleReferenceClick = useCallback((href: string) => { + // 1. 获取当前文档所在的目录 + const currentDir = selectedPath ? selectedPath.split('/').slice(0, -1).join('/') : ''; + + // 2. 解析目标路径 + let targetPath = ''; + if (href.startsWith('/')) { + // 绝对路径(相对于文档根目录) + targetPath = href.slice(1); + } else { + // 相对路径处理 + const parts = currentDir ? currentDir.split('/') : []; + const hrefParts = href.split('/'); + + for (const part of hrefParts) { + if (part === '.') continue; + if (part === '..') { + parts.pop(); + } else { + parts.push(part); + } + } + targetPath = parts.join('/'); + } + + // 3. 规范化目标路径(移除 .md 后缀以便对比,或者直接对比全名) + // 考虑到 externalDocs 中的 relativePath 包含 .md,我们也应该构造包含 .md 的路径 + if (!targetPath.endsWith('.md')) { + targetPath += '.md'; + } + + // 4. 精确查找 + const match = externalDocs.find(d => d.relativePath === targetPath); + + if (match) { + setSelectedPath(match.relativePath) + setCurrentContent(match.content) + } else { + console.warn(`Document not found: ${targetPath}`); + } + }, [externalDocs, selectedPath]) // 添加 selectedPath 依赖 +``` + +## 3. 影响与验证 +- **影响**:修复了所有相对路径链接的跳转逻辑,不再会出现跨目录同名文件乱跳的情况。 +- **验证**:点击 `rhi/buffer/d3d12/buffer.md` 中的 `initialize.md`,应该正确跳转到同目录下的 `rhi/buffer/d3d12/initialize.md`。 \ No newline at end of file diff --git a/.trae/documents/fix_link_color_plan.md b/.trae/documents/fix_link_color_plan.md new file mode 100644 index 0000000..a81f4a7 --- /dev/null +++ b/.trae/documents/fix_link_color_plan.md @@ -0,0 +1,68 @@ +# 修复文档内代码块中链接样式失效问题 + +## 1. 问题分析 +用户反馈“有的是蓝色,有的没有颜色(普通文本)”。 +在 Markdown 文档(特别是 API 文档)中,链接经常出现在代码块或表格内。例如: +`[`Initialize`](initialize.md)` + +在 `DocContent.tsx` 中,我们对 `code` 标签有自定义渲染逻辑: +```typescript + code: ({ className, children, ...props }) => { + const match = /language-(\w+)/.exec(className || '') + if (match) { + // ... 代码高亮块 ... + } + // 行内代码 + return ( + + {children} + + ) + }, +``` + +当 Markdown 解析器遇到 `[`Initialize`](initialize.md)` 时,它会生成: +```html +Initialize +``` +或者(取决于解析器行为) +```html +Initialize +``` +但在 `react-markdown` 中,通常链接包裹内容。如果链接内部包含 `code` 标签,`code` 标签的样式(`text-zinc-300`)可能会覆盖外层 `a` 标签的颜色样式(`text-blue-500`)。 +CSS 中,子元素的 `color` 属性通常会覆盖父元素的 `color`。这里 `code` 组件显式设置了 `text-zinc-300`(灰色),导致包裹在链接里的代码块显示为灰色,看起来像没有颜色的普通文本。 + +## 2. 修复方案 + +### 修改文件: `src/components/DocContent.tsx` + +我们需要调整 `code` 组件的样式逻辑。如果 `code` 标签被包裹在 `a` 标签中,它应该继承父元素的颜色,而不是强制使用 `text-zinc-300`。 +但在 `react-markdown` 的组件渲染中,子组件很难直接知道父组件是谁。 + +**替代方案**:利用 CSS 的 `inherit` 特性或移除显式的颜色类。 +更稳妥的方法是:修改 `code` 组件的 `className`,让它不强制设置颜色,或者仅在非链接环境下设置颜色。 +或者,我们可以给 `a` 标签内的内容强制应用蓝色。 + +**最佳实践**: +修改 `code` 组件的渲染,不再强制 `text-zinc-300`,而是使用一个默认颜色,但允许被父级覆盖。或者,我们在 `a` 组件中,给子元素强制颜色。 + +鉴于 `react-markdown` 的结构,最简单有效的方法是在 `code` 组件中移除 `text-zinc-300`,改为使用 `bg-zinc-800` 等背景色来区分代码块,字体颜色让其继承或使用更弱的默认值。 +但为了保持非链接代码块的灰色外观,我们可以尝试在 CSS (Tailwind) 中使用 `group` 或直接在 `a` 标签样式中强制子元素颜色。 + +**修改计划**: +1. 修改 `a` 组件:添加 `group` 类。 +2. 修改 `code` 组件:添加 `group-hover:text-blue-400` (这可能不行,因为 code 不是 a 的直接子组件,react 渲染树中它们是分离的组件函数)。 + +**更直接的方案**: +在 `code` 组件中,移除 `text-zinc-300`,改为 `text-inherit` 或者不设置颜色类(让其继承),然后在全局或父级容器设置默认文本颜色。 +或者,简单粗暴地:在 `a` 标签的 `className` 中添加 `[&>code]:text-blue-500` (Tailwind 任意变体语法),强制 `a` 标签下的 `code` 元素变成蓝色。 + +```typescript +// 在 a 标签组件中 +className="text-blue-500 hover:text-blue-400 transition-colors cursor-pointer [&>code]:text-blue-500 [&>code]:hover:text-blue-400" +``` +这样可以确保链接内的代码块也显示为蓝色。 + +## 3. 影响与验证 +- **影响**:所有被链接包裹的行内代码块(如 `[`Code`](link)`)都将变为蓝色,表明它们是可点击的链接。普通行内代码块保持原样(如果它们不在 a 标签内)。 +- **验证**:查看包含 `[`Initialize`](...)` 的文档,确认 "Initialize" 显示为蓝色且可点击。 \ No newline at end of file diff --git a/.trae/documents/fix_link_navigation_plan.md b/.trae/documents/fix_link_navigation_plan.md new file mode 100644 index 0000000..cfb0ffa --- /dev/null +++ b/.trae/documents/fix_link_navigation_plan.md @@ -0,0 +1,57 @@ +# 修复文档内链接跳转白屏问题计划 + +## 1. 问题分析 +用户反馈“点击链接直接白屏了”。这是因为在 Markdown 文档内容中,部分相对链接(例如 `[Some Doc](SomeDoc.md)`)没有以 `./` 或 `../` 开头。 +目前的 `DocContent.tsx` 组件在渲染 `` 标签时,仅拦截了以 `./` 或 `../` 开头的链接。对于其他格式的本地链接,它会渲染为原生的 `` 标签。 +在 Electron 或单页应用(SPA)中,点击原生链接会触发浏览器的默认导航行为,试图跳转到该文件路径,从而导致 React 应用被卸载(变成白屏或显示 404/纯文本)。 + +以前用户可以通过左侧树直接点击叶子节点查看文档,但在我们隐藏了叶子节点后,用户必须依赖文档内的链接进行导航,导致这个原本就存在的链接跳转问题暴露了出来。 + +## 2. 修改方案 + +### 修改文件: `src/components/DocContent.tsx` +调整 Markdown 中 `` 标签的渲染逻辑,拦截所有本地链接,阻止默认的页面跳转行为,并将其交给内部的 `onReferenceClick` 处理: + +1. **识别内部链接**: + 判断 `href` 是否存在,且**不以** `http://`、`https://`、`mailto:` 或 `#` 开头。满足此条件的都视为内部文档链接。 + +2. **阻止默认行为并触发内部跳转**: + 对于内部链接,渲染为 `` 标签,但在 `onClick` 事件中调用 `e.preventDefault()` 阻止白屏跳转,随后调用 `onReferenceClick(href)`。 + +```typescript + a: ({ href, children }) => { + // 判断是否是内部链接:非 http/https,非邮箱,非页内锚点 + const isInternal = href && !href.startsWith('http') && !href.startsWith('mailto:') && !href.startsWith('#'); + + if (isInternal) { + return ( + { + e.preventDefault(); + onReferenceClick(href); + }} + className="text-blue-500 hover:text-blue-400 transition-colors cursor-pointer" + > + {children} + + ) + } + + // 外部链接保留默认行为,但新窗口打开更安全 + return ( + + {children} + + ) + }, +``` + +## 3. 影响与验证 +- **影响**:所有的内部 Markdown 链接现在都会通过 React 状态更新右侧内容,而不会触发导致白屏的浏览器原生导航。 +- **验证**:保存修改后,点击文档内部的普通文件名链接(如 `SomeDoc.md`),页面将平滑切换到目标文档内容,不再出现白屏崩溃现象。 \ No newline at end of file diff --git a/.trae/documents/hide_leaf_nodes_plan.md b/.trae/documents/hide_leaf_nodes_plan.md new file mode 100644 index 0000000..1b30c07 --- /dev/null +++ b/.trae/documents/hide_leaf_nodes_plan.md @@ -0,0 +1,39 @@ +# 隐藏层级树叶子节点实现计划 + +## 1. 目标概述 +在 API 文档界面的左侧层级树(`DocTree` 组件)中,隐藏所有的叶子节点(即具体的 Markdown 文件),使目录树仅展示文件夹(目录)结构。 + +## 2. 现状分析 +- 目前 `src/components/DocTree.tsx` 中的 `DocTree` 和 `TreeNode` 组件会无差别地渲染所有传入的节点(包含文件夹和文件)。 +- 树状图的连线UI(如 `├─` 和 `└─`)依赖于数组的索引和长度(`isLast` 属性)。如果仅在渲染时隐式返回 `null`,会导致连线计算错误。 +- 在当前的交互中,点击文件夹会默认打开与文件夹同名的 Markdown 索引文件(此时 `selectedPath` 是该 `.md` 文件的路径)。如果隐藏了文件节点,需要确保此时对应的文件夹能被正确高亮显示。 + +## 3. 具体修改方案 + +### 修改文件: `src/components/DocTree.tsx` + +**1. 过滤子节点并修复连线逻辑 (在 `TreeNode` 组件中)** +- 在渲染子节点之前,先过滤出 `isDir === true` 的节点: + ```typescript + const visibleChildren = file.children?.filter(c => c.isDir) + const showChildren = isDir && isExpanded && visibleChildren && visibleChildren.length > 0 + ``` +- 在 `visibleChildren.map` 中渲染子节点,并基于 `visibleChildren.length` 来计算 `isLast`,确保树状图的连线完美闭合。 + +**2. 完善文件夹高亮逻辑 (在 `TreeNode` 组件中)** +- 修改 `isSelected` 的判断,使得当子文件(与文件夹同名的索引文档)被选中时,该文件夹节点也能呈现高亮状态: + ```typescript + const isSelected = selectedPath === file.relativePath || + (isDir && selectedPath === `${file.relativePath}/${file.name}.md`) + ``` + +**3. 过滤根节点 (在 `DocTree` 组件中)** +- 在渲染根层级前过滤出文件夹: + ```typescript + const visibleFiles = files.filter(f => f.isDir) + ``` +- 基于 `visibleFiles` 遍历并传递正确的 `isLast` 属性。 + +## 4. 影响与验证 +- **影响**:所有的独立 `.md` 文件将不再出现在左侧树中,用户需要通过点击目录(加载索引页)和页面内的文档链接来进行页面导航。 +- **验证**:保存修改后,左侧目录树将只显示文件夹图标/层级;连线正常;点击文件夹后,当前文件夹名称会变为高亮蓝色(`text-blue-400`)。 \ No newline at end of file diff --git a/docs/api/containers/array/array.md b/docs/api/containers/array/array.md new file mode 100644 index 0000000..d743c30 --- /dev/null +++ b/docs/api/containers/array/array.md @@ -0,0 +1,67 @@ +# Array + +**命名空间**: `XCEngine::Containers` + +**类型**: `class` (template) + +**描述**: 模板动态数组容器,提供自动扩容的数组实现。 + +## 概述 + +`Array` 是一个模板动态数组容器,提供了类似 `std::vector` 的功能,但针对游戏引擎进行了优化。 + +## 类型别名 + +| 别名 | 类型 | 描述 | +|------|------|------| +| `Iterator` | `T*` | 迭代器类型 | +| `ConstIterator` | `const T*` | 常量迭代器类型 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [Constructor](constructor.md) | 构造数组实例 | +| [Copy/Move Constructor](copy-move-constructor.md) | 拷贝或移动构造 | +| [Destructor](destructor.md) | 析构函数 | +| [operator=](operator-assign.md) | 赋值运算符 | +| [operator[]](operator-subscript.md) | 下标访问 | +| [Data](data.md) | 获取原始数据指针 | +| [Front/Back](front-back.md) | 获取首/尾元素引用 | +| [Size/Capacity/Empty](size.md) | 获取尺寸信息 | +| [Clear](clear.md) | 清空所有元素 | +| [Reserve](reserve.md) | 预留容量 | +| [Resize](resize.md) | 调整大小 | +| [PushBack](pushback.md) | 尾部添加(拷贝/移动) | +| [EmplaceBack](emplaceback.md) | 就地构造尾部添加 | +| [PopBack](popback.md) | 尾部移除 | +| [begin/end](iterator.md) | 获取迭代器 | +| [SetAllocator](setallocator.md) | 设置内存分配器 | + +## 使用示例 + +```cpp +#include + +// 基本用法 +XCEngine::Containers::Array arr; +arr.PushBack(1); +arr.PushBack(2); +arr.PushBack(3); + +// 使用 initializer_list +XCEngine::Containers::Array arr2 = {1, 2, 3, 4, 5}; + +// 迭代 +for (auto& elem : arr) { + printf("%d\n", elem); +} + +// 使用 EmplaceBack +arr.EmplaceBack(4); +``` + +## 相关文档 + +- [HashMap](../hashmap/hashmap.md) - 哈希表容器 +- [Memory 模块](../../memory/memory.md) - 内存分配器 diff --git a/docs/api/containers/array/clear.md b/docs/api/containers/array/clear.md new file mode 100644 index 0000000..d0b59ae --- /dev/null +++ b/docs/api/containers/array/clear.md @@ -0,0 +1,36 @@ +# Array::Clear() + +```cpp +void Clear(); +``` + +清空数组中的所有元素。 + +**行为:** +- 调用所有元素的析构函数 +- 将 `Size()` 设为 0 +- **不释放底层内存**,`Capacity()` 保持不变 + +**线程安全:** ❌ 清空期间不可并发访问 + +**示例:** + +```cpp +Containers::Array arr = {1, 2, 3, 4, 5}; + +arr.Size(); // 5 +arr.Capacity(); // 8(假设自动扩容到 8) + +arr.Clear(); + +arr.Size(); // 0 +arr.Capacity(); // 8(内存未被释放) + +// 可继续添加元素,不会重新分配内存 +arr.PushBack(10); +arr.PushBack(20); +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/constructor.md b/docs/api/containers/array/constructor.md new file mode 100644 index 0000000..421f485 --- /dev/null +++ b/docs/api/containers/array/constructor.md @@ -0,0 +1,44 @@ +# Array::Array() + +```cpp +Array() = default; +explicit Array(size_t capacity); +Array(size_t count, const T& value); +Array(std::initializer_list init); +``` + +构造一个 `Array` 实例。 + +**默认构造**:构造空数组,不分配内存。 + +**容量构造**:预分配指定容量的内存,但不设置元素数量。适用于已知大致元素数量时减少重新分配。 + +**数量构造**:创建 `count` 个元素,每个元素都是 `value` 的拷贝。使用拷贝构造,不调用默认构造。 + +**初始化列表构造**:使用 C++ initializer_list 语法创建数组。 + +**参数:** +- `capacity` - 预分配的容量大小 +- `count` - 元素数量 +- `value` - 每个元素的初始值 +- `init` - initializer_list 初始化列表 + +**示例:** + +```cpp +// 默认构造 +Containers::Array arr1; + +// 预分配容量(不设置元素) +Containers::Array arr2(100); + +// 创建 10 个元素,初始值为 42 +Containers::Array arr3(10, 42); + +// 使用 initializer_list +Containers::Array arr4 = {1, 2, 3, 4, 5}; +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/copy-move-constructor.md b/docs/api/containers/array/copy-move-constructor.md new file mode 100644 index 0000000..4811dc7 --- /dev/null +++ b/docs/api/containers/array/copy-move-constructor.md @@ -0,0 +1,44 @@ +# Array::Array() - 拷贝/移动构造 + +```cpp +Array(const Array& other); +Array(Array&& other) noexcept; +``` + +拷贝或移动构造一个新数组。 + +**拷贝构造:** +- 分配与 `other` 相同容量的内存 +- 拷贝 `other` 中所有元素 + +**移动构造:** +- 接管 `other` 的所有资源(数据指针、容量、大小) +- 将 `other` 置为空状态(`m_data = nullptr, m_size = 0, m_capacity = 0`) +- 不拷贝、不移动任何元素数据,性能 O(1) + +**参数:** +- `other` - 源数组 + +**异常:** +- 拷贝构造:元素拷贝可能抛出异常 +- 移动构造:`noexcept`,不抛出异常 + +**线程安全:** ❌ 构造期间不可并发访问 + +**示例:** + +```cpp +Containers::Array arr1 = {1, 2, 3}; + +// 拷贝构造 +Containers::Array arr2(arr1); // arr2 = {1, 2, 3} + +// 移动构造 +Containers::Array arr3(std::move(arr1)); +// arr3 = {1, 2, 3} +// arr1 现在为空,Size() == 0 +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/data.md b/docs/api/containers/array/data.md new file mode 100644 index 0000000..8cd2afb --- /dev/null +++ b/docs/api/containers/array/data.md @@ -0,0 +1,30 @@ +# Array::Data() + +```cpp +T* Data(); +const T* Data() const; +``` + +获取指向底层数组数据的原始指针。 + +**用途:** 用于与 C 风格 API 或需要直接访问内存的场景(如与 GPU 通信)。 + +**返回:** 指向底层连续内存块的指针。如果数组为空,返回 `nullptr`。 + +**复杂度:** O(1) + +**示例:** + +```cpp +Containers::Array arr = {1.0f, 2.0f, 3.0f}; + +float* raw = arr.Data(); +size_t count = arr.Size(); + +// 可用于与 C API 交互 +// memcpy(dst, arr.Data(), arr.Size() * sizeof(float)); +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/destructor.md b/docs/api/containers/array/destructor.md new file mode 100644 index 0000000..34cce96 --- /dev/null +++ b/docs/api/containers/array/destructor.md @@ -0,0 +1,28 @@ +# Array::~Array() + +```cpp +~Array(); +``` + +销毁数组,释放所有已分配的元素并释放内存。 + +**行为:** +- 调用所有元素的析构函数 +- 释放底层数据缓冲区内存 + +**注意:** 使用 RAII 模式,无需手动调用析构。 + +**线程安全:** ❌ 析构期间不可并发访问 + +**示例:** + +```cpp +{ + Containers::Array arr = {1, 2, 3}; + // 使用 arr... +} // arr 在此自动销毁,析构函数被调用 +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/emplaceback.md b/docs/api/containers/array/emplaceback.md new file mode 100644 index 0000000..d1e3e2b --- /dev/null +++ b/docs/api/containers/array/emplaceback.md @@ -0,0 +1,47 @@ +# Array::EmplaceBack() + +```cpp +template +T& EmplaceBack(Args&&... args); +``` + +在数组末尾就地构造一个元素,直接在内存中构造,不产生临时对象。 + +**优势:** +- 避免拷贝或移动开销 +- 直接在底层缓冲区末尾构造元素 +- 参数完美转发,支持任意构造参数 + +**参数:** +- `args` - 转发给 `T` 构造函数的参数包 + +**返回:** 新构造元素的引用 + +**复杂度:** 均摊 O(1) + +**线程安全:** ❌ 操作期间不可并发访问 + +**示例:** + +```cpp +struct Vertex { + float x, y, z; + Vertex(float x_, float y_, float z_) : x(x_), y(y_), z(z_) {} +}; + +Containers::Array vertices; + +// EmplaceBack 直接构造,不产生临时 Vertex 对象 +vertices.EmplaceBack(1.0f, 2.0f, 3.0f); +vertices.EmplaceBack(4.0f, 5.0f, 6.0f); + +// 对比 PushBack(需要先构造临时对象) +Vertex v(7.0f, 8.0f, 9.0f); +vertices.PushBack(v); // 产生拷贝或移动 + +// EmplaceBack 更高效,始终优先使用 +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/front-back.md b/docs/api/containers/array/front-back.md new file mode 100644 index 0000000..e37d697 --- /dev/null +++ b/docs/api/containers/array/front-back.md @@ -0,0 +1,38 @@ +# Array::Front() / Back() + +```cpp +T& Front(); +const T& Front() const; +T& Back(); +const T& Back() const; +``` + +获取数组首尾元素的引用。 + +**Front():** 返回第一个元素(`index == 0`)的引用。 + +**Back():** 返回最后一个元素(`index == Size() - 1`)的引用。 + +**前置条件:** 数组必须非空,否则行为未定义。 + +**返回:** 首/尾元素的引用 + +**复杂度:** O(1) + +**线程安全:** ❌ 访问期间不可并发修改 + +**示例:** + +```cpp +Containers::Array arr = {10, 20, 30}; + +int& first = arr.Front(); // first == 10 +int& last = arr.Back(); // last == 30 + +arr.Front() = 5; // arr 现在是 {5, 20, 30} +arr.Back() = 100; // arr 现在是 {5, 20, 100} +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/iterator.md b/docs/api/containers/array/iterator.md new file mode 100644 index 0000000..e5d6364 --- /dev/null +++ b/docs/api/containers/array/iterator.md @@ -0,0 +1,45 @@ +# Array::begin() / end() + +```cpp +Iterator begin(); +Iterator end(); +ConstIterator begin() const; +ConstIterator end() const; +``` + +获取数组的迭代器,用于范围遍历。 + +**begin():** 返回指向第一个元素的迭代器。如果数组为空,返回值等于 `end()`。 + +**end():** 返回指向"最后一个元素之后"位置的迭代器(哨兵)。这是一个越界位置,不可解引用。 + +**迭代器类型:** `Iterator = T*`(原始指针),因此支持指针算术运算。 + +**复杂度:** O(1) + +**线程安全:** ❌ 迭代期间不可并发修改数组 + +**示例:** + +```cpp +Containers::Array arr = {10, 20, 30, 40, 50}; + +// 范围 for 循环(推荐) +for (int val : arr) { + printf("%d\n", val); +} + +// 手动迭代器 +for (auto it = arr.begin(); it != arr.end(); ++it) { + printf("%d\n", *it); +} + +// 指针算术(因为迭代器就是指针) +int* ptr = arr.begin(); +ptr += 2; // 指向第三个元素 +*ptr; // 30 +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/operator-assign.md b/docs/api/containers/array/operator-assign.md new file mode 100644 index 0000000..84f9bc9 --- /dev/null +++ b/docs/api/containers/array/operator-assign.md @@ -0,0 +1,44 @@ +# Array::operator= + +```cpp +Array& operator=(const Array& other); +Array& operator=(Array&& other) noexcept; +``` + +赋值运算符,用另一个数组的内容替换当前数组的内容。 + +**拷贝赋值(`=`):** +- 先销毁当前所有元素 +- 分配与 `other` 相同大小的内存 +- 拷贝 `other` 中所有元素 + +**移动赋值(`=`):** +- 先销毁当前所有元素 +- 接管 `other` 的所有资源(数据指针、容量) +- 将 `other` 置为空状态 + +**参数:** +- `other` - 源数组 + +**返回:** 引用自身(`*this`) + +**异常:** +- 拷贝赋值:`other` 元素拷贝可能抛出异常 + +**线程安全:** ❌ 赋值期间不可并发访问 + +**示例:** + +```cpp +Containers::Array arr1 = {1, 2, 3}; +Containers::Array arr2; + +arr2 = arr1; // 拷贝赋值,arr2 现在是 {1, 2, 3} + +Containers::Array arr3 = {4, 5}; +arr2 = std::move(arr3); // 移动赋值,arr2 现在是 {4, 5},arr3 为空 +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/operator-subscript.md b/docs/api/containers/array/operator-subscript.md new file mode 100644 index 0000000..7f74e53 --- /dev/null +++ b/docs/api/containers/array/operator-subscript.md @@ -0,0 +1,39 @@ +# Array::operator[] + +```cpp +T& operator[](size_t index); +const T& operator[](size_t index) const; +``` + +按下标访问数组元素,不进行边界检查。 + +**行为:** +- 返回指定索引处元素的引用 +- 不进行下标越界检查,性能最优 +- 可用于读取和修改元素(非常量版本) + +**参数:** +- `index` - 元素下标,从 0 开始 + +**返回:** 元素的引用(常量版本返回常量引用) + +**复杂度:** O(1) + +**线程安全:** ❌ 访问元素期间不可并发修改 + +**注意:** 不会进行边界检查。如果 `index >= Size()`,行为未定义。如需边界检查,请使用 `At()` 方法(如果存在)或自行检查。 + +**示例:** + +```cpp +Containers::Array arr = {10, 20, 30}; + +int first = arr[0]; // first == 10 +int last = arr[2]; // last == 30 + +arr[1] = 25; // arr 现在是 {10, 25, 30} +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/popback.md b/docs/api/containers/array/popback.md new file mode 100644 index 0000000..8762a6f --- /dev/null +++ b/docs/api/containers/array/popback.md @@ -0,0 +1,38 @@ +# Array::PopBack() + +```cpp +void PopBack(); +``` + +移除数组末尾的元素,并调用其析构函数。 + +**前置条件:** 数组必须非空(`Size() > 0`)。如果数组为空,行为未定义。 + +**行为:** +- 将 `Size()` 减 1 +- 调用被移除元素的析构函数 +- **不释放底层内存** + +**线程安全:** ❌ 操作期间不可并发访问 + +**示例:** + +```cpp +Containers::Array arr = {10, 20, 30, 40, 50}; + +arr.Size(); // 5 + +arr.PopBack(); // 移除 50 + +arr.Size(); // 4 +// arr = {10, 20, 30, 40} + +arr.PopBack(); +arr.PopBack(); +// arr = {10, 20} +// Capacity() 仍为之前的值(如 8) +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/pushback.md b/docs/api/containers/array/pushback.md new file mode 100644 index 0000000..741ad85 --- /dev/null +++ b/docs/api/containers/array/pushback.md @@ -0,0 +1,43 @@ +# Array::PushBack() + +```cpp +void PushBack(const T& value); +void PushBack(T&& value); +``` + +在数组末尾添加一个元素。 + +**拷贝版本(`const T&`):** +- 如果容量不足(`Size() >= Capacity()`),先扩容(容量翻倍) +- 在末尾位置拷贝构造 `value` + +**移动版本(`T&&`):** +- 行为同拷贝版本,但使用移动构造 +- 适用于临时对象或右值,避免拷贝开销 + +**参数:** +- `value` - 要添加的元素(拷贝或移动) + +**复杂度:** 均摊 O(1)。每次添加的摊销成本为常数,因为扩容是翻倍策略。 + +**线程安全:** ❌ 操作期间不可并发访问 + +**示例:** + +```cpp +Containers::Array arr; + +// 拷贝添加 +std::string s = "hello"; +arr.PushBack(s); // s 被拷贝 + +// 移动添加(更高效) +arr.PushBack(std::string("world")); // 直接移动构造 + +// 临时对象会被隐式移动 +arr.PushBack("temporary"); // 字符串字面量构造后移动 +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/reserve.md b/docs/api/containers/array/reserve.md new file mode 100644 index 0000000..310263f --- /dev/null +++ b/docs/api/containers/array/reserve.md @@ -0,0 +1,39 @@ +# Array::Reserve() + +```cpp +void Reserve(size_t capacity); +``` + +预分配底层内存容量,确保能容纳至少 `capacity` 个元素而不重新分配。 + +**行为:** +- 如果 `capacity > Capacity()`,分配新的内存(容量翻倍策略) +- 如果 `capacity <= Capacity()`,什么都不做 +- 不改变 `Size()` + +**参数:** +- `capacity` - 目标容量 + +**用途:** 当已知大致元素数量时,提前分配可以避免多次重新分配带来的性能开销和迭代器失效。 + +**复杂度:** O(n),其中 n 为当前元素数量(需要拷贝现有元素到新内存) + +**线程安全:** ❌ 操作期间不可并发访问 + +**示例:** + +```cpp +Containers::Array arr; + +// 预分配 1000 个元素的容量 +arr.Reserve(1000); + +// 之后添加 500 个元素不会触发重新分配 +for (int i = 0; i < 500; ++i) { + arr.PushBack(i); +} +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/resize.md b/docs/api/containers/array/resize.md new file mode 100644 index 0000000..f29d109 --- /dev/null +++ b/docs/api/containers/array/resize.md @@ -0,0 +1,46 @@ +# Array::Resize() + +```cpp +void Resize(size_t newSize); +void Resize(size_t newSize, const T& value); +``` + +调整数组大小。 + +**Resize(newSize):** +- 如果 `newSize > Size()`:在末尾构造 `newSize - Size()` 个默认构造的元素 +- 如果 `newSize < Size()`:销毁末尾多出的元素 +- 如果 `newSize == Size()`:什么都不做 + +**Resize(newSize, value):** +- 行为同上述,但扩展时使用 `value` 拷贝构造新元素,而非默认构造 + +**参数:** +- `newSize` - 新的元素数量 +- `value` - 扩展时用作填充值的元素 + +**复杂度:** O(n),涉及元素构造/析构和可能的内存重新分配 + +**线程安全:** ❌ 操作期间不可并发访问 + +**示例:** + +```cpp +Containers::Array arr = {1, 2, 3}; + +// 扩展到 5 个元素,新元素默认构造为 0 +arr.Resize(5); +// arr = {1, 2, 3, 0, 0} + +// 缩减到 2 个元素 +arr.Resize(2); +// arr = {1, 2} + +// 扩展到 4 个,填充为 -1 +arr.Resize(4, -1); +// arr = {1, 2, -1, -1} +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/setallocator.md b/docs/api/containers/array/setallocator.md new file mode 100644 index 0000000..c6b6be4 --- /dev/null +++ b/docs/api/containers/array/setallocator.md @@ -0,0 +1,38 @@ +# Array::SetAllocator() + +```cpp +void SetAllocator(Memory::IAllocator* allocator); +``` + +设置数组使用的内存分配器。 + +**用途:** 允许自定义内存分配策略,如使用对象池、固定大小分配器或调试分配器。 + +**参数:** +- `allocator` - 指向 `Memory::IAllocator` 接口的指针。如果为 `nullptr`,使用默认 `::operator new/delete`。 + +**注意:** +- 如果数组已有元素,设置新的分配器后,**不会**迁移现有元素 +- 仅影响后续的内存分配操作 +- 通常在构造后立即调用,或在数组为空时调用 + +**线程安全:** ❌ 操作期间不可并发访问 + +**示例:** + +```cpp +// 使用线性分配器(适合帧分配) +auto* linear = new Memory::LinearAllocator(1024 * 1024); + +Containers::Array arr; +arr.SetAllocator(linear); + +// 使用对象池分配器 +auto* pool = new Memory::PoolAllocator(sizeof(MyObject), 100); +Containers::Array objects; +objects.SetAllocator(pool); +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/array/size.md b/docs/api/containers/array/size.md new file mode 100644 index 0000000..1077f29 --- /dev/null +++ b/docs/api/containers/array/size.md @@ -0,0 +1,47 @@ +# Array::Size() / Capacity() / Empty() + +```cpp +size_t Size() const; +size_t Capacity() const; +bool Empty() const; +``` + +获取数组的尺寸信息。 + +**Size():** 返回数组中的实际元素数量。 + +**Capacity():** 返回底层内存缓冲区能容纳的元素数量,不一定等于 `Size()`。 + +**Empty():** 返回数组是否为空(`Size() == 0`)。等价于 `Size() == 0`,但更语义化。 + +**返回:** +- `Size()` - 元素数量 +- `Capacity()` - 底层缓冲区容量 +- `Empty()` - 是否为空 + +**复杂度:** O(1) + +**示例:** + +```cpp +Containers::Array arr; + +arr.Size(); // 0 +arr.Capacity(); // 0 +arr.Empty(); // true + +arr.PushBack(1); +arr.PushBack(2); + +arr.Size(); // 2 +arr.Capacity(); // 4(自动扩容) +arr.Empty(); // false + +arr.Reserve(100); +arr.Size(); // 2(元素数量不变) +arr.Capacity(); // 100(容量增加) +``` + +## 相关文档 + +- [Array 总览](array.md) - 返回类总览 diff --git a/docs/api/containers/containers.md b/docs/api/containers/containers.md new file mode 100644 index 0000000..54ec313 --- /dev/null +++ b/docs/api/containers/containers.md @@ -0,0 +1,57 @@ +# Containers 容器模块概览 + +**命名空间**: `XCEngine::Containers` + +**类型**: `module` + +**描述**: XCEngine 的容器模块,提供常用的数据结构实现。 + +## 概述 + +Containers 模块提供了图形引擎常用的数据结构,包括动态数组、字符串和哈希表。这些容器都使用自定义内存分配器接口,支持内存跟踪和优化。 + +## 模块内容 + +### 容器类 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [Array](array/array.md) | `Array.h` | 模板动态数组,支持自动扩容 | +| [String](string/string.md) | `String.h` | 动态字符串类 | +| [HashMap](hashmap/hashmap.md) | `HashMap.h` | 模板哈希表 | + +## 设计特点 + +1. **自定义内存分配器支持** - 所有容器都支持通过 `IAllocator` 接口分配内存 +2. **迭代器支持** - Array 和 HashMap 都提供 STL 风格的迭代器 +3. **移动语义** - 完整支持 C++11 移动语义 +4. **异常安全** - 内存分配失败时提供良好的错误处理 + +## 使用示例 + +```cpp +#include +#include +#include + +// 使用 Array +XCEngine::Containers::Array arr; +arr.PushBack(1); +arr.PushBack(2); +arr.PushBack(3); + +// 使用 String +XCEngine::Containers::String str; +str = "Hello, "; +str += "World!"; + +// 使用 HashMap +XCEngine::Containers::HashMap map; +map.Insert("key1", 100); +map.Insert("key2", 200); +int* value = map.Find("key1"); +``` + +## 相关文档 + +- [Memory 模块](../memory/memory.md) - 内存分配器接口 diff --git a/docs/api/containers/hashmap/clear.md b/docs/api/containers/hashmap/clear.md new file mode 100644 index 0000000..fc8facd --- /dev/null +++ b/docs/api/containers/hashmap/clear.md @@ -0,0 +1,34 @@ +# HashMap::Clear + +```cpp +void Clear(); +``` + +清空哈希表中的所有元素,将元素数量置为 0。桶的数量保持不变。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(m_bucketCount),需要清空所有桶 + +**示例:** + +```cpp +XCEngine::Containers::HashMap map; +map.Insert(1, "one"); +map.Insert(2, "two"); +map.Insert(3, "three"); + +std::cout << "Size before clear: " << map.Size() << std::endl; // 输出 3 + +map.Clear(); + +std::cout << "Size after clear: " << map.Size() << std::endl; // 输出 0 +std::cout << "Empty: " << (map.Empty() ? "yes" : "no") << std::endl; // 输出 "yes" +``` + +## 相关文档 + +- [HashMap 总览](hashmap.md) - 返回类总览 +- [Erase](erase.md) - 删除单个元素 diff --git a/docs/api/containers/hashmap/constructor.md b/docs/api/containers/hashmap/constructor.md new file mode 100644 index 0000000..6930a52 --- /dev/null +++ b/docs/api/containers/hashmap/constructor.md @@ -0,0 +1,31 @@ +# HashMap::HashMap + +```cpp +HashMap(); +explicit HashMap(size_t bucketCount, Memory::IAllocator* allocator = nullptr); +``` + +构造哈希表实例。 + +**参数:** +- `bucketCount` - 初始桶的数量,默认为 16。若传入 0,则自动调整为 16。 +- `allocator` - 内存分配器指针,默认为 `nullptr`(使用默认分配器)。 + +**返回:** 无 + +**复杂度:** O(bucketCount),需要初始化所有桶 + +**示例:** + +```cpp +XCEngine::Containers::HashMap map1; + +XCEngine::Containers::HashMap map2(32); + +auto customAllocator = XCEngine::Memory::GetDefaultAllocator(); +XCEngine::Containers::HashMap map3(64, customAllocator); +``` + +## 相关文档 + +- [HashMap 总览](hashmap.md) - 返回类总览 diff --git a/docs/api/containers/hashmap/contains.md b/docs/api/containers/hashmap/contains.md new file mode 100644 index 0000000..ff0f5db --- /dev/null +++ b/docs/api/containers/hashmap/contains.md @@ -0,0 +1,35 @@ +# HashMap::Contains + +```cpp +bool Contains(const Key& key) const; +``` + +检查哈希表中是否包含指定的键。 + +**参数:** +- `key` - 要检查的键 + +**返回:** 如果键存在返回 `true`,否则返回 `false`。 + +**复杂度:** O(1) 平均,最坏 O(n) + +**示例:** + +```cpp +XCEngine::Containers::HashMap map; +map.Insert(1, "one"); +map.Insert(2, "two"); + +if (map.Contains(1)) { + std::cout << "Key 1 exists" << std::endl; // 输出 "Key 1 exists" +} + +if (!map.Contains(99)) { + std::cout << "Key 99 does not exist" << std::endl; // 输出 "Key 99 does not exist" +} +``` + +## 相关文档 + +- [HashMap 总览](hashmap.md) - 返回类总览 +- [Find](find.md) - 查找键对应的值 diff --git a/docs/api/containers/hashmap/copy-move.md b/docs/api/containers/hashmap/copy-move.md new file mode 100644 index 0000000..4eacdea --- /dev/null +++ b/docs/api/containers/hashmap/copy-move.md @@ -0,0 +1,34 @@ +# HashMap::Copy/Move 构造 + +```cpp +HashMap(const HashMap& other); +HashMap(HashMap&& other) noexcept; +``` + +拷贝构造和移动构造。 + +**参数:** +- `other` - 源哈希表(拷贝版本为 `const` 引用,移动版本为右值引用) + +**返回:** 无(构造函数) + +**复杂度:** +- 拷贝构造:O(m_bucketCount + other.m_size) +- 移动构造:O(m_bucketCount),移动构造需要遍历所有桶以重新建立桶的指针关系 + +**示例:** + +```cpp +XCEngine::Containers::HashMap map1; +map1.Insert(1, "hello"); +map1.Insert(2, "world"); + +XCEngine::Containers::HashMap map2(map1); // 拷贝构造 + +XCEngine::Containers::HashMap map3(std::move(map1)); // 移动构造,map1 在此调用后状态不确定 +``` + +## 相关文档 + +- [HashMap 总览](hashmap.md) - 返回类总览 +- [operator=](operator-assign.md) - 赋值运算符 diff --git a/docs/api/containers/hashmap/destructor.md b/docs/api/containers/hashmap/destructor.md new file mode 100644 index 0000000..1274b16 --- /dev/null +++ b/docs/api/containers/hashmap/destructor.md @@ -0,0 +1,27 @@ +# HashMap::~HashMap + +```cpp +~HashMap(); +``` + +析构函数,清空所有元素并释放资源。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n),需要清空所有桶中的元素 + +**示例:** + +```cpp +{ + XCEngine::Containers::HashMap map; + map.Insert(1, "hello"); + map.Insert(2, "world"); +} // map 在此自动析构,所有资源被正确释放 +``` + +## 相关文档 + +- [HashMap 总览](hashmap.md) - 返回类总览 diff --git a/docs/api/containers/hashmap/erase.md b/docs/api/containers/hashmap/erase.md new file mode 100644 index 0000000..02df0ea --- /dev/null +++ b/docs/api/containers/hashmap/erase.md @@ -0,0 +1,37 @@ +# HashMap::Erase + +```cpp +bool Erase(const Key& key); +``` + +删除指定键对应的元素。 + +**参数:** +- `key` - 要删除的键 + +**返回:** 如果元素被删除返回 `true`,如果键不存在返回 `false`。 + +**复杂度:** O(1) 平均,最坏 O(n) + +**示例:** + +```cpp +XCEngine::Containers::HashMap map; +map.Insert(1, "one"); +map.Insert(2, "two"); +map.Insert(3, "three"); + +bool erased = map.Erase(2); // 返回 true + +if (!map.Contains(2)) { + std::cout << "Key 2 removed" << std::endl; // 输出 "Key 2 removed" +} + +bool notErased = map.Erase(99); // 返回 false,键不存在 +``` + +## 相关文档 + +- [HashMap 总览](hashmap.md) - 返回类总览 +- [Insert](insert.md) - 插入键值对 +- [Clear](clear.md) - 清空所有元素 diff --git a/docs/api/containers/hashmap/find.md b/docs/api/containers/hashmap/find.md new file mode 100644 index 0000000..5f6c78f --- /dev/null +++ b/docs/api/containers/hashmap/find.md @@ -0,0 +1,39 @@ +# HashMap::Find + +```cpp +Value* Find(const Key& key); +const Value* Find(const Key& key) const; +``` + +根据键查找对应的值指针。 + +**参数:** +- `key` - 要查找的键 + +**返回:** 如果找到,返回指向值的指针;否则返回 `nullptr`。 + +**复杂度:** O(1) 平均,最坏 O(n)(同一桶中有多个键发生哈希冲突) + +**示例:** + +```cpp +XCEngine::Containers::HashMap map; +map.Insert(1, "one"); +map.Insert(2, "two"); + +const char* value1 = map.Find(1); +if (value1) { + std::cout << "Found: " << value1 << std::endl; // 输出 "Found: one" +} + +const char* value2 = map.Find(99); +if (!value2) { + std::cout << "Not found" << std::endl; // 输出 "Not found" +} +``` + +## 相关文档 + +- [HashMap 总览](hashmap.md) - 返回类总览 +- [Contains](contains.md) - 检查是否包含键 +- [operator[]](./operator-subscript.md) - 下标访问 diff --git a/docs/api/containers/hashmap/hashmap.md b/docs/api/containers/hashmap/hashmap.md new file mode 100644 index 0000000..96b5998 --- /dev/null +++ b/docs/api/containers/hashmap/hashmap.md @@ -0,0 +1,80 @@ +# HashMap + +**命名空间**: `XCEngine::Containers` + +**类型**: `class` (template) + +**描述**: 模板哈希表容器,提供键值对存储和快速查找。 + +## 概述 + +`HashMap` 是一个模板哈希表容器,使用动态数组作为桶来解决哈希冲突,支持键值对的插入、查找和删除操作。 + +## 公共类型 + +### Pair + +| 成员 | 类型 | 描述 | +|------|------|------| +| `first` | `Key` | 键 | +| `second` | `Value` | 值 | + +### 迭代器 + +| 别名 | 类型 | 描述 | +|------|------|------| +| `Iterator` | `typename Array::Iterator` | 迭代器类型 | +| `ConstIterator` | `typename Array::ConstIterator` | 常量迭代器类型 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [Constructor](constructor.md) | 构造哈希表实例 | +| [Destructor](destructor.md) | 析构函数 | +| [operator=](operator-assign.md) | 赋值运算符 | +| [Copy/Move](copy-move.md) | 拷贝/移动构造 | +| [operator[]](operator-subscript.md) | 下标访问(不存在时插入) | +| [Find](find.md) | 查找键对应的值指针 | +| [Contains](contains.md) | 检查是否包含键 | +| [Insert](insert.md) | 插入键值对 | +| [Erase](erase.md) | 删除键对应的元素 | +| [Clear](clear.md) | 清空所有元素 | +| [Size/Empty](size.md) | 获取元素数量 | +| [begin/end](iterator.md) | 获取迭代器 | +| [SetAllocator](setallocator.md) | 设置内存分配器 | + +## 使用示例 + +```cpp +#include +#include + +int main() { + XCEngine::Containers::HashMap map; + + map.Insert(1, "one"); + map.Insert(2, "two"); + map.Insert(3, "three"); + + if (const char* value = map.Find(1)) { + std::cout << "Key 1: " << value << std::endl; + } + + std::cout << "Size: " << map.Size() << std::endl; + + for (auto it = map.begin(); it != map.end(); ++it) { + std::cout << it->first << " -> " << it->second << std::endl; + } + + map.Erase(2); + std::cout << "Contains 2: " << (map.Contains(2) ? "yes" : "no") << std::endl; + + return 0; +} +``` + +## 相关文档 + +- [Array](../array/array.md) - 动态数组 +- [Memory 模块](../../memory/memory.md) - 内存分配器 diff --git a/docs/api/containers/hashmap/insert.md b/docs/api/containers/hashmap/insert.md new file mode 100644 index 0000000..ad582ac --- /dev/null +++ b/docs/api/containers/hashmap/insert.md @@ -0,0 +1,38 @@ +# HashMap::Insert + +```cpp +bool Insert(const Key& key, const Value& value); +bool Insert(const Key& key, Value&& value); +bool Insert(Pair&& pair); +``` + +插入键值对。如果键已存在,则更新其值并返回 `false`;否则插入新元素并返回 `true`。 + +**参数:** +- `key` - 要插入的键 +- `value` - 要插入的值(const 版本为拷贝,&& 版本为移动) +- `pair` - 包含键值对的 `Pair` 结构(右值) + +**返回:** 如果插入成功(键不存在)返回 `true`,如果键已存在(更新值)返回 `false`。 + +**复杂度:** O(1) 平均,最坏 O(n)(包括可能的 rehash) + +**示例:** + +```cpp +XCEngine::Containers::HashMap map; + +bool inserted1 = map.Insert(1, "one"); // 返回 true +bool inserted2 = map.Insert(1, "ONE"); // 返回 false,更新现有值 + +bool inserted3 = map.Insert(2, std::string("two")); // 移动语义版本 + +XCEngine::Containers::HashMap::Pair p{3, "three"}; +bool inserted4 = map.Insert(std::move(p)); // Pair 移动版本 +``` + +## 相关文档 + +- [HashMap 总览](hashmap.md) - 返回类总览 +- [operator[]](./operator-subscript.md) - 下标访问(总是插入) +- [Erase](erase.md) - 删除键对应的元素 diff --git a/docs/api/containers/hashmap/iterator.md b/docs/api/containers/hashmap/iterator.md new file mode 100644 index 0000000..62e3cb2 --- /dev/null +++ b/docs/api/containers/hashmap/iterator.md @@ -0,0 +1,34 @@ +# HashMap::begin / end + +```cpp +Iterator begin(); +Iterator end(); +ConstIterator begin() const; +ConstIterator end() const; +``` + +获取哈希表的迭代器。迭代器遍历所有桶中的元素。 + +**参数:** 无 + +**返回:** 返回指向第一个元素和末尾(最后一个元素之后)位置的迭代器。 + +**复杂度:** O(1) + +**示例:** + +```cpp +XCEngine::Containers::HashMap map; +map.Insert(1, "one"); +map.Insert(2, "two"); +map.Insert(3, "three"); + +for (auto it = map.begin(); it != map.end(); ++it) { + std::cout << it->first << " -> " << it->second << std::endl; +} +// 输出顺序不确定,取决于哈希桶的内部布局 +``` + +## 相关文档 + +- [HashMap 总览](hashmap.md) - 返回类总览 diff --git a/docs/api/containers/hashmap/operator-assign.md b/docs/api/containers/hashmap/operator-assign.md new file mode 100644 index 0000000..d439ab9 --- /dev/null +++ b/docs/api/containers/hashmap/operator-assign.md @@ -0,0 +1,36 @@ +# HashMap::operator= + +```cpp +HashMap& operator=(const HashMap& other); +HashMap& operator=(HashMap&& other) noexcept; +``` + +赋值运算符,用另一个 HashMap 的内容替换当前内容。 + +**参数:** +- `other` - 源哈希表(拷贝版本为 `const` 引用,移动版本为右值引用) + +**返回:** 对当前对象的引用 (`*this`) + +**复杂度:** +- 拷贝赋值:O(m_bucketCount + other.m_size) +- 移动赋值:O(m_size),需要先清空当前内容 + +**示例:** + +```cpp +XCEngine::Containers::HashMap map1; +map1.Insert(1, "one"); +map1.Insert(2, "two"); + +XCEngine::Containers::HashMap map2; +map2 = map1; // 拷贝赋值 + +XCEngine::Containers::HashMap map3; +map3 = std::move(map1); // 移动赋值,map1 在此调用后状态不确定 +``` + +## 相关文档 + +- [HashMap 总览](hashmap.md) - 返回类总览 +- [Copy/Move](copy-move.md) - 拷贝/移动构造 diff --git a/docs/api/containers/hashmap/operator-subscript.md b/docs/api/containers/hashmap/operator-subscript.md new file mode 100644 index 0000000..6f77157 --- /dev/null +++ b/docs/api/containers/hashmap/operator-subscript.md @@ -0,0 +1,33 @@ +# HashMap::operator[] + +```cpp +Value& operator[](const Key& key); +``` + +按下标访问键对应的值。如果键不存在,则插入一个默认构造的值并返回引用。 + +**参数:** +- `key` - 要访问的键 + +**返回:** 对应值的引用。如果键不存在,则返回一个默认构造的 `Value` 的引用。 + +**复杂度:** O(1) 平均,最坏 O(n)(发生 rehash 时) + +**示例:** + +```cpp +XCEngine::Containers::HashMap map; + +map[1] = "one"; // 插入键 1,值 "one" +map[2] = "two"; // 插入键 2,值 "two" + +std::string& value = map[1]; // 获取键 1 对应的值,结果为 "one" + +map[3]; // 插入键 3,值为 std::string 的默认构造值 +``` + +## 相关文档 + +- [HashMap 总览](hashmap.md) - 返回类总览 +- [Find](find.md) - 查找键对应的值(不插入) +- [Insert](insert.md) - 插入键值对(不覆盖已存在的键) diff --git a/docs/api/containers/hashmap/setallocator.md b/docs/api/containers/hashmap/setallocator.md new file mode 100644 index 0000000..b272bfd --- /dev/null +++ b/docs/api/containers/hashmap/setallocator.md @@ -0,0 +1,28 @@ +# HashMap::SetAllocator + +```cpp +void SetAllocator(Memory::IAllocator* allocator); +``` + +设置哈希表的内存分配器。 + +**参数:** +- `allocator` - 内存分配器指针,可以为 `nullptr`(使用默认分配器) + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +XCEngine::Containers::HashMap map; + +// 设置自定义分配器(如果使用内存分配器接口) +// map.SetAllocator(customAllocator); +``` + +## 相关文档 + +- [HashMap 总览](hashmap.md) - 返回类总览 +- [Memory 模块](../../memory/memory.md) - 内存分配器 diff --git a/docs/api/containers/hashmap/size.md b/docs/api/containers/hashmap/size.md new file mode 100644 index 0000000..40b40be --- /dev/null +++ b/docs/api/containers/hashmap/size.md @@ -0,0 +1,35 @@ +# HashMap::Size / Empty + +```cpp +size_t Size() const; +bool Empty() const; +``` + +获取哈希表的元素数量或判断是否为空。 + +**参数:** 无 + +**返回:** +- `Size()` - 返回元素数量 +- `Empty()` - 容器为空返回 `true`,否则返回 `false` + +**复杂度:** O(1) + +**示例:** + +```cpp +XCEngine::Containers::HashMap map; + +std::cout << "Empty: " << (map.Empty() ? "yes" : "no") << std::endl; // 输出 "yes" +std::cout << "Size: " << map.Size() << std::endl; // 输出 0 + +map.Insert(1, "one"); +map.Insert(2, "two"); + +std::cout << "Empty: " << (map.Empty() ? "yes" : "no") << std::endl; // 输出 "no" +std::cout << "Size: " << map.Size() << std::endl; // 输出 2 +``` + +## 相关文档 + +- [HashMap 总览](hashmap.md) - 返回类总览 diff --git a/docs/api/containers/string/clear.md b/docs/api/containers/string/clear.md new file mode 100644 index 0000000..af9c064 --- /dev/null +++ b/docs/api/containers/string/clear.md @@ -0,0 +1,39 @@ +# String::Clear + +```cpp +void Clear(); +``` + +清空字符串内容,将长度设为 0,但不释放已分配的内存。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s("Hello World"); + std::cout << "Before clear - Length: " << s.Length() + << ", Capacity: " << s.Capacity() << std::endl; + // 输出: Before clear - Length: 11, Capacity: 12 + + s.Clear(); + std::cout << "After clear - Length: " << s.Length() + << ", Capacity: " << s.Capacity() << std::endl; + // 输出: After clear - Length: 0, Capacity: 12 + std::cout << "Empty: " << s.Empty() << std::endl; // 输出: Empty: 1 + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 +- [Reserve / Resize](reserve-resize.md) - 内存管理 diff --git a/docs/api/containers/string/constructor.md b/docs/api/containers/string/constructor.md new file mode 100644 index 0000000..f1967eb --- /dev/null +++ b/docs/api/containers/string/constructor.md @@ -0,0 +1,48 @@ +# String::String + +```cpp +String(); +String(const char* str); +String(const char* str, SizeType len); +String(const String& other); +String(String&& other) noexcept; +``` + +构造 String 对象。提供多种构造方式以适应不同的使用场景。 + +**参数:** +- `str` - 以 null 结尾的 C 字符串 +- `len` - 要复制的字符数量 +- `other` - 另一个 String 对象(用于拷贝构造或移动构造) + +**返回:** 无 + +**复杂度:** +- 默认构造:O(1) +- 从 `const char*` 构造:O(n),其中 n 为字符串长度 +- 拷贝构造:O(n) +- 移动构造:O(1) + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s1; // 默认构造 + XCEngine::Containers::String s2("hello"); // 从 C 字符串构造 + XCEngine::Containers::String s3("world", 3); // 从 C 字符串前 n 个字符构造 + XCEngine::Containers::String s4(s2); // 拷贝构造 + XCEngine::Containers::String s5(std::move(s4)); // 移动构造 + + std::cout << s2.CStr() << std::endl; // 输出: hello + std::cout << s3.CStr() << std::endl; // 输出: wor + std::cout << s4.CStr() << std::endl; // 输出: hello + std::cout << s5.CStr() << std::endl; // 输出: hello + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 diff --git a/docs/api/containers/string/cstr.md b/docs/api/containers/string/cstr.md new file mode 100644 index 0000000..7072962 --- /dev/null +++ b/docs/api/containers/string/cstr.md @@ -0,0 +1,36 @@ +# String::CStr + +```cpp +const char* CStr() const; +``` + +返回指向以 null 结尾的 C 字符串的指针。 + +**参数:** 无 + +**返回:** 指向内部字符数组的指针,以 null 结尾 + +**复杂度:** O(1) + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include +#include + +int main() { + XCEngine::Containers::String s("Hello World"); + + const char* cstr = s.CStr(); + std::cout << cstr << std::endl; // 输出: Hello World + + std::cout << "Length: " << std::strlen(cstr) << std::endl; // 输出: Length: 11 + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 +- [Length](size.md) - 获取长度 diff --git a/docs/api/containers/string/destructor.md b/docs/api/containers/string/destructor.md new file mode 100644 index 0000000..49375c9 --- /dev/null +++ b/docs/api/containers/string/destructor.md @@ -0,0 +1,31 @@ +# String::~String + +```cpp +~String(); +``` + +销毁 String 对象,释放所有动态分配的内存。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" + +int main() { + { + XCEngine::Containers::String s("hello"); + // s 在作用域结束时自动销毁 + } + // 内存已释放 + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 diff --git a/docs/api/containers/string/ends-with.md b/docs/api/containers/string/ends-with.md new file mode 100644 index 0000000..aabe335 --- /dev/null +++ b/docs/api/containers/string/ends-with.md @@ -0,0 +1,39 @@ +# String::EndsWith + +```cpp +bool EndsWith(const String& suffix) const; +bool EndsWith(const char* suffix) const; +``` + +检查字符串是否以指定的后缀结尾。 + +**参数:** +- `suffix` - 要检查的后缀(String 或 const char*) + +**返回:** 如果字符串以指定后缀结尾则返回 `true`,否则返回 `false` + +**复杂度:** O(n),其中 n 为后缀长度 + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s("Hello World"); + + std::cout << std::boolalpha; + std::cout << s.EndsWith("World") << std::endl; // 输出: true + std::cout << s.EndsWith(XCEngine::Containers::String("World")) << std::endl; // 输出: true + std::cout << s.EndsWith("Hello") << std::endl; // 输出: false + std::cout << s.EndsWith("") << std::endl; // 输出: true + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 +- [StartsWith](starts-with.md) - 检查前缀 +- [Find](find.md) - 查找子串 diff --git a/docs/api/containers/string/find.md b/docs/api/containers/string/find.md new file mode 100644 index 0000000..652e3d8 --- /dev/null +++ b/docs/api/containers/string/find.md @@ -0,0 +1,47 @@ +# String::Find + +```cpp +SizeType Find(const char* str, SizeType pos = 0) const; +``` + +在字符串中查找子串 `str`,从位置 `pos` 开始搜索。 + +**参数:** +- `str` - 要查找的以 null 结尾的 C 字符串 +- `pos` - 开始搜索的位置,默认为 0 + +**返回:** 子串首次出现的起始位置;如果未找到,返回 `String::npos` + +**复杂度:** O(n * m),其中 n 为原字符串长度,m 为要查找的字符串长度 + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s("Hello World, Hello Universe"); + + XCEngine::Containers::String::SizeType pos1 = s.Find("World"); + std::cout << "Found at: " << pos1 << std::endl; // 输出: Found at: 6 + + XCEngine::Containers::String::SizeType pos2 = s.Find("Hello", 0); + std::cout << "First 'Hello' at: " << pos2 << std::endl; // 输出: First 'Hello' at: 0 + + XCEngine::Containers::String::SizeType pos3 = s.Find("Hello", 7); + std::cout << "Second 'Hello' at: " << pos3 << std::endl; // 输出: Second 'Hello' at: 13 + + XCEngine::Containers::String::SizeType pos4 = s.Find("NotFound"); + if (pos4 == XCEngine::Containers::String::npos) { + std::cout << "Not found" << std::endl; // 输出: Not found + } + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 +- [StartsWith](starts-with.md) - 检查前缀 +- [EndsWith](ends-with.md) - 检查后缀 diff --git a/docs/api/containers/string/operator-assign.md b/docs/api/containers/string/operator-assign.md new file mode 100644 index 0000000..e6bd49a --- /dev/null +++ b/docs/api/containers/string/operator-assign.md @@ -0,0 +1,47 @@ +# String::operator= + +```cpp +String& operator=(const String& other); +String& operator=(String&& other) noexcept; +String& operator=(const char* str); +``` + +将新的值赋给 String 对象,替换原有的内容。 + +**参数:** +- `other` - 另一个 String 对象(拷贝赋值或移动赋值) +- `str` - 以 null 结尾的 C 字符串 + +**返回:** `*this`,支持链式调用 + +**复杂度:** +- 拷贝赋值:O(n),n 为 other 的长度 +- 移动赋值:O(1) +- 从 `const char*` 赋值:O(n),n 为 str 的长度 + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s1; + XCEngine::Containers::String s2("hello"); + + s1 = s2; // 拷贝赋值 + std::cout << s1.CStr() << std::endl; // 输出: hello + + s1 = "world"; // 从 const char* 赋值 + std::cout << s1.CStr() << std::endl; // 输出: world + + XCEngine::Containers::String s3("moved"); + s1 = std::move(s3); // 移动赋值 + std::cout << s1.CStr() << std::endl; // 输出: moved + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 diff --git a/docs/api/containers/string/operator-equal.md b/docs/api/containers/string/operator-equal.md new file mode 100644 index 0000000..5d998d5 --- /dev/null +++ b/docs/api/containers/string/operator-equal.md @@ -0,0 +1,43 @@ +# operator== / operator!= + +```cpp +inline bool operator==(const String& lhs, const String& rhs); +inline bool operator!=(const String& lhs, const String& rhs); +``` + +判断两个字符串是否相等或不相等。 + +**operator==:** 比较两个字符串的长度是否相等,以及内容是否相同。 + +**operator!=:** 相当于 `!(lhs == rhs)`。 + +**参数:** +- `lhs` - 左侧字符串 +- `rhs` - 右侧字符串 + +**返回:** 布尔值,表示比较结果 + +**复杂度:** O(n),其中 n 为字符串长度 + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s1("Hello"); + XCEngine::Containers::String s2("Hello"); + XCEngine::Containers::String s3("World"); + + std::cout << std::boolalpha; + std::cout << (s1 == s2) << std::endl; // 输出: true + std::cout << (s1 == s3) << std::endl; // 输出: false + std::cout << (s1 != s3) << std::endl; // 输出: true + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 diff --git a/docs/api/containers/string/operator-plus-assign.md b/docs/api/containers/string/operator-plus-assign.md new file mode 100644 index 0000000..53c3377 --- /dev/null +++ b/docs/api/containers/string/operator-plus-assign.md @@ -0,0 +1,43 @@ +# String::operator+= + +```cpp +String& operator+=(const String& other); +String& operator+=(const char* str); +String& operator+=(char c); +``` + +将指定的内容追加到当前 String 的末尾。 + +**参数:** +- `other` - 要追加的 String 对象 +- `str` - 要追加的以 null 结尾的 C 字符串 +- `c` - 要追加的单个字符 + +**返回:** `*this`,支持链式调用 + +**复杂度:** O(n),其中 n 为被追加内容的长度。可能会触发重新分配,但均摊复杂度为 O(1)。 + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s("Hello"); + + s += XCEngine::Containers::String(" World"); // 追加 String + std::cout << s.CStr() << std::endl; // 输出: Hello World + + s += "!"; // 追加 const char* + std::cout << s.CStr() << std::endl; // 输出: Hello World! + + s += '?'; // 追加 char + std::cout << s.CStr() << std::endl; // 输出: Hello World!? + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 diff --git a/docs/api/containers/string/operator-plus.md b/docs/api/containers/string/operator-plus.md new file mode 100644 index 0000000..8e261ef --- /dev/null +++ b/docs/api/containers/string/operator-plus.md @@ -0,0 +1,39 @@ +# operator+ + +```cpp +inline String operator+(const String& lhs, const String& rhs); +``` + +将两个 String 对象连接,返回一个新的 String 对象。 + +**参数:** +- `lhs` - 左侧的 String 对象 +- `rhs` - 右侧的 String 对象 + +**返回:** 新的 String 对象,内容为 lhs 和 rhs 的拼接 + +**复杂度:** O(n + m),其中 n 和 m 分别为 lhs 和 rhs 的长度 + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s1("Hello"); + XCEngine::Containers::String s2(" World"); + XCEngine::Containers::String s3 = s1 + s2; + + std::cout << s3.CStr() << std::endl; // 输出: Hello World + + XCEngine::Containers::String s4 = XCEngine::Containers::String("Foo") + "Bar"; + std::cout << s4.CStr() << std::endl; // 输出: FooBar + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 +- [operator+=](operator-plus-assign.md) - 追加操作 diff --git a/docs/api/containers/string/operator-subscript.md b/docs/api/containers/string/operator-subscript.md new file mode 100644 index 0000000..bb01021 --- /dev/null +++ b/docs/api/containers/string/operator-subscript.md @@ -0,0 +1,51 @@ +# String::operator[] + +```cpp +char& operator[](SizeType index); +const char& operator[](SizeType index) const; +``` + +通过索引访问字符串中的字符。 + +**参数:** +- `index` - 要访问的字符位置(从 0 开始) + +**返回:** 位置 `index` 处字符的引用(可写或只读) + +**复杂度:** O(1) + +**注意:** 不进行边界检查。调用者需确保 `index < Length()`。 + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s("Hello"); + + // 只读访问 + for (XCEngine::Containers::String::SizeType i = 0; i < s.Length(); ++i) { + std::cout << s[i]; + } + std::cout << std::endl; // 输出: Hello + + // 可写访问 + s[0] = 'J'; + s[1] = 'a'; + s[4] = '!'; + std::cout << s.CStr() << std::endl; // 输出: Jallo! + + // const 版本 + const XCEngine::Containers::String& cs = s; + char first = cs[0]; + std::cout << "First char: " << first << std::endl; // 输出: First char: J + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 +- [Length](size.md) - 获取长度 diff --git a/docs/api/containers/string/reserve-resize.md b/docs/api/containers/string/reserve-resize.md new file mode 100644 index 0000000..fb2a87c --- /dev/null +++ b/docs/api/containers/string/reserve-resize.md @@ -0,0 +1,51 @@ +# String::Reserve / Resize + +```cpp +void Reserve(SizeType capacity); +void Resize(SizeType newSize); +void Resize(SizeType newSize, char fillChar); +``` + +管理字符串的内存和大小。 + +**参数:** +- `capacity` - 要预留的最小容量 +- `newSize` - 新的字符串长度 +- `fillChar` - 当扩展字符串时用于填充新增位置的字符,默认为 '\0' + +**返回:** 无 + +**复杂度:** +- `Reserve`:最坏 O(n),仅在需要扩展容量时复制数据 +- `Resize`:O(n),当 newSize > Length 时可能需要扩展 + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s("Hi"); + + // Reserve - 预分配内存 + s.Reserve(100); + std::cout << "After Reserve(100), Capacity: " << s.Capacity() << std::endl; + // 输出: After Reserve(100), Capacity: 100 + + // Resize - 缩短字符串 + s.Resize(1); + std::cout << "After Resize(1): " << s.CStr() << std::endl; // 输出: H + + // Resize - 扩展字符串,用 'X' 填充 + s.Resize(5, 'X'); + std::cout << "After Resize(5, 'X'): " << s.CStr() << std::endl; // 输出: HXXXX + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 +- [Length / Capacity](size.md) - 获取长度和容量 +- [Clear](clear.md) - 清空字符串 diff --git a/docs/api/containers/string/size.md b/docs/api/containers/string/size.md new file mode 100644 index 0000000..9084722 --- /dev/null +++ b/docs/api/containers/string/size.md @@ -0,0 +1,44 @@ +# String::Length / Capacity / Empty + +```cpp +SizeType Length() const; +SizeType Capacity() const; +bool Empty() const; +``` + +获取字符串的长度、容量和判空状态。 + +**参数:** 无 + +**返回:** +- `Length()` - 返回字符串的字符数(不包括终止 null 字符) +- `Capacity()` - 返回已分配的存储容量 +- `Empty()` - 如果字符串为空则返回 `true` + +**复杂度:** 均为 O(1) + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s1; + std::cout << "Empty: " << s1.Empty() << std::endl; // 输出: Empty: 1 + + XCEngine::Containers::String s2("Hello"); + std::cout << "Length: " << s2.Length() << std::endl; // 输出: Length: 5 + std::cout << "Capacity: " << s2.Capacity() << std::endl; // 输出: Capacity: 6 或更大 + + s2.Reserve(100); + std::cout << "After Reserve(100), Capacity: " << s2.Capacity() << std::endl; // 输出: 100 + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 +- [CStr](cstr.md) - 获取 C 字符串 +- [Reserve / Resize](reserve-resize.md) - 内存管理 diff --git a/docs/api/containers/string/starts-with.md b/docs/api/containers/string/starts-with.md new file mode 100644 index 0000000..1ee0447 --- /dev/null +++ b/docs/api/containers/string/starts-with.md @@ -0,0 +1,39 @@ +# String::StartsWith + +```cpp +bool StartsWith(const String& prefix) const; +bool StartsWith(const char* prefix) const; +``` + +检查字符串是否以指定的前缀开头。 + +**参数:** +- `prefix` - 要检查的前缀(String 或 const char*) + +**返回:** 如果字符串以指定前缀开头则返回 `true`,否则返回 `false` + +**复杂度:** O(n),其中 n 为前缀长度 + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s("Hello World"); + + std::cout << std::boolalpha; + std::cout << s.StartsWith("Hello") << std::endl; // 输出: true + std::cout << s.StartsWith(XCEngine::Containers::String("Hello")) << std::endl; // 输出: true + std::cout << s.StartsWith("World") << std::endl; // 输出: false + std::cout << s.StartsWith("") << std::endl; // 输出: true + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 +- [EndsWith](ends-with.md) - 检查后缀 +- [Find](find.md) - 查找子串 diff --git a/docs/api/containers/string/string.md b/docs/api/containers/string/string.md new file mode 100644 index 0000000..0f425be --- /dev/null +++ b/docs/api/containers/string/string.md @@ -0,0 +1,105 @@ +# String + +**命名空间**: `XCEngine::Containers` + +**类型**: `class` + +**描述**: 动态字符串类,提供 UTF-8 编码的字符串操作。 + +## 概述 + +`String` 是一个自定义动态字符串类,提供常见的字符串操作功能,支持拷贝构造、移动构造和多种字符串操作方法。 + +## 类型别名 + +| 别名 | 类型 | 描述 | +|------|------|------| +| `SizeType` | `size_t` | 大小类型 | + +## 常量 + +| 常量 | 值 | 描述 | +|------|-----|------| +| `static constexpr SizeType npos` | `static_cast(-1)` | 无效位置标识 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [Constructor](constructor.md) | 构造字符串实例 | +| [Destructor](destructor.md) | 析构函数 | +| [operator=](operator-assign.md) | 赋值运算符 | +| [operator+=](operator-plus-assign.md) | 追加字符串/字符 | +| [operator+](../string/operator-plus.md) | 字符串连接 | +| [operator==](../string/operator-equal.md) | 判断两个字符串是否相等 | +| [operator!=](../string/operator-equal.md) | 判断两个字符串是否不相等 | +| [Substring](substring.md) | 获取子串 | +| [Trim](trim.md) | 去除首尾空白 | +| [ToLower/ToUpper](to-lower-upper.md) | 大小写转换 | +| [Find](find.md) | 查找子串位置 | +| [StartsWith](starts-with.md) | 检查前缀 | +| [EndsWith](ends-with.md) | 检查后缀 | +| [CStr](cstr.md) | 获取 C 字符串指针 | +| [Length/Capacity/Empty](size.md) | 获取尺寸信息 | +| [operator[]](operator-subscript.md) | 下标访问 | +| [Clear](clear.md) | 清空字符串 | +| [Reserve/Resize](reserve-resize.md) | 预留/调整容量 | + +## std::hash 特化 + +```cpp +namespace std { + template<> + struct hash { + size_t operator()(const XCEngine::Containers::String& str) const noexcept; + }; +} +``` + +提供了 `std::hash` 特化,使 `String` 可以作为 unordered_map 或 unordered_set 的键使用。 + +**实现算法:** DJB hash (Daniel J. Bernstein hash) + +**算法细节:** +- 初始值:5381 +- 对每个字符:`hash = hash * 33 + c`(等价于 `(hash << 5) + hash + c`) + +**示例:** +```cpp +#include +#include + +int main() { + std::unordered_map map; + map["key1"] = 100; + map["key2"] = 200; + return 0; +} +``` + +## 使用示例 + +```cpp +#include + +// 基本用法 +Containers::String str = "Hello"; +str += ", World!"; + +// 字符串操作 +Containers::String sub = str.Substring(0, 5); // "Hello" +bool hasPrefix = str.StartsWith("Hello"); +bool hasSuffix = str.EndsWith("!"); + +// 查找 +SizeType pos = str.Find("World"); // 返回 7 + +// 转换 +Containers::String upper = str.ToUpper(); +Containers::String lower = str.ToLower(); +``` + +## 相关文档 + +- [Array](../array/array.md) - 动态数组 +- [HashMap](../hashmap/hashmap.md) - 哈希表 diff --git a/docs/api/containers/string/substring.md b/docs/api/containers/string/substring.md new file mode 100644 index 0000000..9b479eb --- /dev/null +++ b/docs/api/containers/string/substring.md @@ -0,0 +1,43 @@ +# String::Substring + +```cpp +String Substring(SizeType pos, SizeType len = npos) const; +``` + +返回从位置 `pos` 开始、长度为 `len` 的子字符串。如果 `len` 省略或为 `npos`,则返回从 `pos` 到字符串末尾的所有字符。 + +**参数:** +- `pos` - 子字符串的起始位置(从 0 开始) +- `len` - 子字符串的长度,默认为 `npos`(即到字符串末尾) + +**返回:** 新的 String 对象,包含指定的子字符串 + +**复杂度:** O(n),其中 n 为子字符串的长度 + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s("Hello World"); + + XCEngine::Containers::String sub1 = s.Substring(6); // 从位置6到末尾 + std::cout << sub1.CStr() << std::endl; // 输出: World + + XCEngine::Containers::String sub2 = s.Substring(6, 5); // 从位置6开始,长度5 + std::cout << sub2.CStr() << std::endl; // 输出: World + + XCEngine::Containers::String sub3 = s.Substring(0, 5); // 从位置0开始,长度5 + std::cout << sub3.CStr() << std::endl; // 输出: Hello + + XCEngine::Containers::String sub4 = s.Substring(6, 100); // len超过剩余长度,自动截断 + std::cout << sub4.CStr() << std::endl; // 输出: World + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 diff --git a/docs/api/containers/string/to-lower-upper.md b/docs/api/containers/string/to-lower-upper.md new file mode 100644 index 0000000..8ad2d58 --- /dev/null +++ b/docs/api/containers/string/to-lower-upper.md @@ -0,0 +1,36 @@ +# String::ToLower / ToUpper + +```cpp +String ToLower() const; +String ToUpper() const; +``` + +将字符串转换为小写/大写形式,返回一个新的 String 对象,原字符串不变。 + +**参数:** 无 + +**返回:** 转换后的新 String 对象 + +**复杂度:** O(n),其中 n 为字符串长度 + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s("Hello World 123"); + + XCEngine::Containers::String lower = s.ToLower(); + std::cout << lower.CStr() << std::endl; // 输出: hello world 123 + + XCEngine::Containers::String upper = s.ToUpper(); + std::cout << upper.CStr() << std::endl; // 输出: HELLO WORLD 123 + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 diff --git a/docs/api/containers/string/trim.md b/docs/api/containers/string/trim.md new file mode 100644 index 0000000..21a1433 --- /dev/null +++ b/docs/api/containers/string/trim.md @@ -0,0 +1,35 @@ +# String::Trim + +```cpp +String Trim() const; +``` + +移除字符串两端的空白字符(空格、制表符、换行符、回车符),返回一个新的 String 对象,原字符串不变。 + +**参数:** 无 + +**返回:** 去除两端空白后的新 String 对象 + +**复杂度:** O(n),其中 n 为字符串长度 + +**示例:** +```cpp +#include "XCEngine/Containers/String.h" +#include + +int main() { + XCEngine::Containers::String s(" Hello World "); + + XCEngine::Containers::String trimmed = s.Trim(); + std::cout << "\"" << trimmed.CStr() << "\"" << std::endl; // 输出: "Hello World" + + XCEngine::Containers::String s2("\t\n test \t\n"); + std::cout << "\"" << s2.Trim().CStr() << "\"" << std::endl; // 输出: "test" (空格、制表符、换行、回车被移除) + + return 0; +} +``` + +## 相关文档 + +- [String 总览](string.md) - 返回类总览 diff --git a/docs/api/core/core.md b/docs/api/core/core.md new file mode 100644 index 0000000..03239b3 --- /dev/null +++ b/docs/api/core/core.md @@ -0,0 +1,97 @@ +# Core 模块概览 + +**命名空间**: `XCEngine::Core` + +**类型**: `module` + +**描述**: XCEngine 的核心基础模块,提供类型别名、智能指针、事件系统等基础功能。 + +## 概述 + +Core 模块包含了引擎所需的基础类型和工具,是其他所有模块的依赖基础。 + +## 模块内容 + +### 类型 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [Types](types/types.md) | `Types.h` | 类型别名定义 | + +### 智能指针 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [SmartPtr](smartptr/smartptr.md) | `SmartPtr.h` | 智能指针别名和工厂函数 | +| [RefCounted](refcounted/refcounted.md) | `RefCounted.h` | 引用计数基类 | + +### 事件系统 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [Event](event/event.md) | `Event.h` | 事件系统模板 | + +### 文件操作 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [FileWriter](filewriter/filewriter.md) | `FileWriter.h` | 文件写入工具 | + +## 类型别名 + +```cpp +using int8 = int8_t; +using int16 = int16_t; +using int32 = int32_t; +using int64 = int64_t; +using uint8 = uint8_t; +using uint16 = uint16_t; +using uint32 = uint32_t; +using uint64 = uint64_t; +using byte = uint8_t; +``` + +## 智能指针别名 + +```cpp +template +using Ref = std::shared_ptr; + +template +using UniqueRef = std::unique_ptr; + +template +Ref MakeRef(Args&&... args); + +template +UniqueRef MakeUnique(Args&&... args); +``` + +## 使用示例 + +```cpp +#include +#include + +using namespace XCEngine::Core; + +// 使用类型别名 +uint32 value = 100; +byte data[4]; + +// 使用智能指针 +auto ref = MakeRef(); +auto unique = MakeUnique(); + +// 使用事件系统 +Event myEvent; +myEvent.Subscribe([](int a, float b) { + printf("Event: %d, %f\n", a, b); +}); +myEvent.Invoke(42, 3.14f); +``` + +## 相关文档 + +- [Containers 模块](../containers/containers.md) - 容器类型 +- [Memory 模块](../memory/memory.md) - 内存管理 diff --git a/docs/api/core/event/Clear.md b/docs/api/core/event/Clear.md new file mode 100644 index 0000000..3d49bf9 --- /dev/null +++ b/docs/api/core/event/Clear.md @@ -0,0 +1,39 @@ +# Event::Clear + +```cpp +void Clear(); +``` + +清空所有订阅。 + +**描述** + +移除所有已订阅的回调,清空事件。线程安全。 + +**复杂度:** O(n) 其中 n 为订阅数量 + +**示例:** + +```cpp +#include + +using namespace XCEngine::Core; + +Event event; + +// 订阅多个回调 +event.Subscribe([](int v) { }); +event.Subscribe([](int v) { }); +event.Subscribe([](int v) { }); + +// 清空所有订阅 +event.Clear(); + +// 触发(无回调被执行) +event.Invoke(42); +``` + +## 相关文档 + +- [Event 总览](event.md) - 返回类总览 +- [Unsubscribe](Unsubscribe.md) - 退订单个事件 diff --git a/docs/api/core/event/Invoke.md b/docs/api/core/event/Invoke.md new file mode 100644 index 0000000..1cd708a --- /dev/null +++ b/docs/api/core/event/Invoke.md @@ -0,0 +1,45 @@ +# Event::Invoke + +```cpp +void Invoke(Args... args); +``` + +调用所有订阅的回调。 + +**描述** + +依次调用所有已订阅的回调函数。在调用前会自动处理待退订的回调。回调是在锁外执行的,因此可以在回调中安全地进行订阅/退订操作。线程安全。 + +**参数:** +- `args` - 传递给回调的参数 + +**复杂度:** O(n) 其中 n 为订阅数量 + +**示例:** + +```cpp +#include + +using namespace XCEngine::Core; + +// 无参数事件 +Event<> frameEndEvent; +frameEndEvent.Subscribe([]() { + printf("Frame ended\n"); +}); + +// 带参数事件 +Event playerDiedEvent; +playerDiedEvent.Subscribe([](int playerId, const char* reason) { + printf("Player %d died: %s\n", playerId, reason); +}); + +// 触发事件 +frameEndEvent.Invoke(); +playerDiedEvent.Invoke(1, "fell off a cliff"); +``` + +## 相关文档 + +- [Event 总览](event.md) - 返回类总览 +- [Subscribe](Subscribe.md) - 订阅事件 diff --git a/docs/api/core/event/ProcessUnsubscribes.md b/docs/api/core/event/ProcessUnsubscribes.md new file mode 100644 index 0000000..32bcbf7 --- /dev/null +++ b/docs/api/core/event/ProcessUnsubscribes.md @@ -0,0 +1,39 @@ +# Event::ProcessUnsubscribes + +```cpp +void ProcessUnsubscribes(); +``` + +处理积压的退订请求。 + +**描述** + +手动处理待退订的回调,将其从订阅列表中移除。通常不需要手动调用,`Invoke` 会自动处理退订。但在某些场景下可能需要主动调用。 + +**复杂度:** O(n) 其中 n 为待退订数量 + +**示例:** + +```cpp +#include + +using namespace XCEngine::Core; + +Event event; + +// 订阅 +uint64_t id = event.Subscribe([](int value) { }); + +// 退订请求入队 +event.Unsubscribe(id); + +// 主动处理退订 +event.ProcessUnsubscribes(); + +// 此时事件列表中已无该回调 +``` + +## 相关文档 + +- [Event 总览](event.md) - 返回类总览 +- [Unsubscribe](Unsubscribe.md) - 退订事件 diff --git a/docs/api/core/event/Subscribe.md b/docs/api/core/event/Subscribe.md new file mode 100644 index 0000000..6f961f5 --- /dev/null +++ b/docs/api/core/event/Subscribe.md @@ -0,0 +1,50 @@ +# Event::Subscribe + +```cpp +uint64_t Subscribe(Callback callback); +``` + +订阅事件回调。 + +**描述** + +将回调函数添加到事件订阅列表中,并返回一个唯一的订阅 ID。该 ID 可用于后续退订。线程安全,可在任意线程调用。 + +**参数:** +- `callback` - 要订阅的回调函数,类型为 `std::function` + +**返回:** `uint64_t` - 订阅 ID,用于退订 + +**复杂度:** O(1) amortized + +**示例:** + +```cpp +#include + +using namespace XCEngine::Core; + +// 定义事件 +Event damageEvent; + +// 订阅多个回调 +uint64_t id1 = damageEvent.Subscribe([](int damage, float time) { + printf("Damage taken: %d at time %f\n", damage, time); +}); + +uint64_t id2 = damageEvent.Subscribe([](int damage, float time) { + // 记录伤害日志 +}); + +// 使用 lambda 表达式 +auto callback = [](int damage, float time) { + // 处理伤害 +}; +uint64_t id3 = damageEvent.Subscribe(callback); +``` + +## 相关文档 + +- [Event 总览](event.md) - 返回类总览 +- [Unsubscribe](Unsubscribe.md) - 退订事件 +- [Invoke](Invoke.md) - 触发事件 diff --git a/docs/api/core/event/Unsubscribe.md b/docs/api/core/event/Unsubscribe.md new file mode 100644 index 0000000..821b4de --- /dev/null +++ b/docs/api/core/event/Unsubscribe.md @@ -0,0 +1,43 @@ +# Event::Unsubscribe + +```cpp +void Unsubscribe(uint64_t id); +``` + +退订事件。 + +**描述** + +将指定 ID 的回调从订阅列表中移除。退订是延迟生效的,在调用 `Invoke` 时会一并处理待退订的回调。线程安全,可在任意线程调用。 + +**参数:** +- `id` - 订阅时返回的 ID + +**复杂度:** O(n) 在 Invoke 时处理 + +**示例:** + +```cpp +#include + +using namespace XCEngine::Core; + +Event someEvent; + +// 订阅 +uint64_t id = someEvent.Subscribe([](int value) { + printf("Value: %d\n", value); +}); + +// 退订 +someEvent.Unsubscribe(id); + +// 触发(已退订的回调不会被调用) +someEvent.Invoke(42); +``` + +## 相关文档 + +- [Event 总览](event.md) - 返回类总览 +- [Subscribe](Subscribe.md) - 订阅事件 +- [ProcessUnsubscribes](ProcessUnsubscribes.md) - 手动处理退订 diff --git a/docs/api/core/event/begin.md b/docs/api/core/event/begin.md new file mode 100644 index 0000000..4337dcc --- /dev/null +++ b/docs/api/core/event/begin.md @@ -0,0 +1,37 @@ +# Event::begin + +```cpp +Iterator begin(); +``` + +获取开始迭代器。 + +**描述** + +返回订阅列表的开始迭代器,用于范围for循环遍历所有订阅的回调。 + +**返回:** `Iterator` - 指向第一个监听器的迭代器(等价于 `std::vector::iterator`) + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +using namespace XCEngine::Core; + +Event event; +event.Subscribe([](int v) { printf("Callback 1: %d\n", v); }); +event.Subscribe([](int v) { printf("Callback 2: %d\n", v); }); + +// 遍历所有订阅 +for (auto& [id, callback] : event) { + callback(100); +} +``` + +## 相关文档 + +- [Event 总览](event.md) - 返回类总览 +- [end](end.md) - 获取结束迭代器 diff --git a/docs/api/core/event/end.md b/docs/api/core/event/end.md new file mode 100644 index 0000000..cbbf5d3 --- /dev/null +++ b/docs/api/core/event/end.md @@ -0,0 +1,36 @@ +# Event::end + +```cpp +Iterator end(); +``` + +获取结束迭代器。 + +**描述** + +返回订阅列表的结束迭代器,用于范围for循环遍历所有订阅的回调。 + +**返回:** `Iterator` - 指向末尾的迭代器(等价于 `std::vector::iterator`) + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +using namespace XCEngine::Core; + +Event event; +event.Subscribe([](int v) { printf("Callback: %d\n", v); }); + +// 遍历所有订阅 +for (auto& [id, callback] : event) { + callback(42); +} +``` + +## 相关文档 + +- [Event 总览](event.md) - 返回类总览 +- [begin](begin.md) - 获取开始迭代器 diff --git a/docs/api/core/event/event.md b/docs/api/core/event/event.md new file mode 100644 index 0000000..ce4575c --- /dev/null +++ b/docs/api/core/event/event.md @@ -0,0 +1,69 @@ +# Event + +**命名空间**: `XCEngine::Core` + +**类型**: `class` (template) + +**描述**: 事件系统模板类,提供类型安全的多订阅者事件/委托系统。 + +## 概述 + +`Event` 是一个类型安全的事件发布-订阅系统。它支持多个回调订阅、退订和线程安全的调用。非常适合用于游戏引擎中的事件驱动通信。 + +## 模板参数 + +| 参数 | 描述 | +|------|------| +| `Args...` | 事件回调的参数类型 | + +## 类型别名 + +| 别名 | 类型 | 描述 | +|------|------|------| +| `Callback` | `std::function` | 回调函数类型 | +| `Listener` | `std::pair` | 监听器条目 | +| `Iterator` | `std::vector::iterator` | 迭代器类型 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Subscribe`](Subscribe.md) | 订阅事件回调,返回订阅 ID | +| [`Unsubscribe`](Unsubscribe.md) | 退订事件(延迟生效) | +| [`ProcessUnsubscribes`](ProcessUnsubscribes.md) | 处理积压的退订请求 | +| [`Clear`](Clear.md) | 清空所有订阅 | +| [`Invoke`](Invoke.md) | 调用所有订阅的回调 | +| [`begin`](begin.md) | 获取开始迭代器 | +| [`end`](end.md) | 获取结束迭代器 | + +## 使用示例 + +```cpp +#include + +using namespace XCEngine::Core; + +// 定义事件(无参数) +Event<> frameStartEvent; + +// 定义事件(带参数) +Event damageEvent; + +// 订阅 +uint64_t id = damageEvent.Subscribe([](int damage, float time) { + printf("Damage: %d at time %f\n", damage, time); +}); + +// 触发事件 +damageEvent.Invoke(100, 3.14f); + +// 退订 +damageEvent.Unsubscribe(id); + +// 清空 +frameStartEvent.Clear(); +``` + +## 相关文档 + +- [Core 模块总览](../core.md) - 返回模块总览 diff --git a/docs/api/core/filewriter/Close.md b/docs/api/core/filewriter/Close.md new file mode 100644 index 0000000..85350fe --- /dev/null +++ b/docs/api/core/filewriter/Close.md @@ -0,0 +1,40 @@ +# FileWriter::Close + +```cpp +void Close(); +``` + +关闭文件。 + +**描述** + +关闭当前打开的文件。如果文件未打开,则什么都不做。析构函数会自动调用此方法。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +using namespace XCEngine::Core; + +FileWriter writer; + +if (writer.Open("data.txt")) { + writer.Write("Some data\n"); + writer.Flush(); + writer.Close(); +} + +// 文件已关闭,可再次打开其他文件 +if (writer.Open("other.txt")) { + writer.Write("New content\n"); +} +// 析构时自动关闭 +``` + +## 相关文档 + +- [FileWriter 总览](filewriter.md) - 返回类总览 +- [Open](Open.md) - 打开文件 diff --git a/docs/api/core/filewriter/Flush.md b/docs/api/core/filewriter/Flush.md new file mode 100644 index 0000000..e132609 --- /dev/null +++ b/docs/api/core/filewriter/Flush.md @@ -0,0 +1,45 @@ +# FileWriter::Flush + +```cpp +bool Flush(); +``` + +刷新缓冲区。 + +**描述** + +将缓冲区中的数据强制写入磁盘,确保数据持久化。在写入大量数据后应调用此方法以确保数据已保存。 + +**返回:** `bool` - 是否刷新成功 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include +#include + +using namespace XCEngine::Core; + +FileWriter writer("output.txt"); +if (writer.IsOpen()) { + // 写入大量数据 + for (int i = 0; i < 1000; i++) { + writer.Write("Line "); + writer.Write(std::to_string(i).c_str()); + writer.Write("\n"); + } + + // 刷新确保数据写入磁盘 + writer.Flush(); + + // 数据已安全保存 + writer.Close(); +} +``` + +## 相关文档 + +- [FileWriter 总览](filewriter.md) - 返回类总览 +- [Write](Write.md) - 写入数据 diff --git a/docs/api/core/filewriter/IsOpen.md b/docs/api/core/filewriter/IsOpen.md new file mode 100644 index 0000000..6395743 --- /dev/null +++ b/docs/api/core/filewriter/IsOpen.md @@ -0,0 +1,43 @@ +# FileWriter::IsOpen + +```cpp +bool IsOpen() const; +``` + +检查文件是否已打开。 + +**描述** + +返回文件是否已成功打开并可用于写入。 + +**返回:** `bool` - 文件是否已打开 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +using namespace XCEngine::Core; + +FileWriter writer1; +if (writer1.IsOpen()) { + // 不会执行 + writer1.Write("test"); +} + +// 打开文件 +FileWriter writer2("output.txt"); +if (writer2.IsOpen()) { + printf("File opened successfully\n"); + writer2.Write("Content"); +} else { + printf("Failed to open file\n"); +} +``` + +## 相关文档 + +- [FileWriter 总览](filewriter.md) - 返回类总览 +- [Open](Open.md) - 打开文件 diff --git a/docs/api/core/filewriter/Open.md b/docs/api/core/filewriter/Open.md new file mode 100644 index 0000000..d572e39 --- /dev/null +++ b/docs/api/core/filewriter/Open.md @@ -0,0 +1,53 @@ +# FileWriter::Open + +```cpp +bool Open(const char* filePath, bool append = false); +``` + +打开文件。 + +**描述** + +打开指定路径的文件,准备写入。如果之前已打开文件,会先关闭。返回是否成功打开文件。 + +**参数:** +- `filePath` - 要打开的文件路径 +- `append` - 是否以追加模式打开,默认为覆盖模式 + +**返回:** `bool` - 是否成功打开 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +using namespace XCEngine::Core; + +FileWriter writer; + +// 打开文件(覆盖模式) +if (writer.Open("output.txt")) { + writer.Write("Hello\n"); + writer.Close(); +} + +// 打开文件(追加模式) +if (writer.Open("log.txt", true)) { + writer.Write("Another line\n"); + writer.Flush(); +} + +// 检查是否成功 +FileWriter writer2; +if (!writer2.Open("/invalid/path/file.txt")) { + printf("Failed to open file\n"); +} +``` + +## 相关文档 + +- [FileWriter 总览](filewriter.md) - 返回类总览 +- [Close](Close.md) - 关闭文件 +- [IsOpen](IsOpen.md) - 检查文件状态 diff --git a/docs/api/core/filewriter/Write.md b/docs/api/core/filewriter/Write.md new file mode 100644 index 0000000..ce47d08 --- /dev/null +++ b/docs/api/core/filewriter/Write.md @@ -0,0 +1,48 @@ +# FileWriter::Write + +```cpp +bool Write(const char* data, size_t length); +bool Write(const Containers::String& str); +``` + +写入数据到文件。 + +**描述** + +将数据写入文件。如果文件未打开,操作会失败。 + +**参数:** +- `data` - 要写入的字符数据 +- `length` - 要写入的字节数 +- `str` - 要写入的 String 对象 + +**返回:** `bool` - 是否写入成功 + +**复杂度:** O(n) 其中 n 为写入的字节数 + +**示例:** + +```cpp +#include +#include + +using namespace XCEngine::Core; + +FileWriter writer("output.txt"); +if (writer.IsOpen()) { + // 写入原始字符数组 + writer.Write("Hello, World!", 13); + writer.Write("\n", 1); + + // 写入 String + Containers::String message = "This is a test string"; + writer.Write(message); + + writer.Flush(); +} +``` + +## 相关文档 + +- [FileWriter 总览](filewriter.md) - 返回类总览 +- [Flush](Flush.md) - 刷新缓冲区 diff --git a/docs/api/core/filewriter/filewriter.md b/docs/api/core/filewriter/filewriter.md new file mode 100644 index 0000000..b1fe6b5 --- /dev/null +++ b/docs/api/core/filewriter/filewriter.md @@ -0,0 +1,66 @@ +# FileWriter + +**命名空间**: `XCEngine::Core` + +**类型**: `class` + +**描述**: 文件写入工具类,提供简单的文件写入操作封装。 + +## 概述 + +`FileWriter` 是一个轻量级的文件写入工具,封装了 `FILE*` 接口,提供便捷的字符串和二进制数据写入功能。它支持追加模式和自动资源管理(RAII)。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `FileWriter()` | 默认构造(不打开文件) | +| `FileWriter(const char* filePath, bool append = false)` | 构造并打开文件 | +| `~FileWriter()` | 析构函数,自动关闭文件 | +| [`Open`](Open.md) | 打开文件,append=true 时为追加模式 | +| [`Close`](Close.md) | 关闭文件 | +| [`IsOpen`](IsOpen.md) | 检查文件是否已打开 | +| [`Write`](Write.md) | 写入数据 | +| [`Flush`](Flush.md) | 刷新缓冲区 | + +## 使用示例 + +```cpp +#include +#include + +using namespace XCEngine::Core; + +// 方式1:构造时打开 +FileWriter writer("output.txt", false); +if (writer.IsOpen()) { + writer.Write("Hello, World!\n"); + writer.Write("Line 2\n"); + writer.Flush(); +} + +// 方式2:先构造再打开 +FileWriter writer2; +if (writer2.Open("log.txt")) { + writer2.Write("Application started\n"); + writer2.Close(); +} + +// 追加模式 +FileWriter appendWriter("log.txt", true); +if (appendWriter.IsOpen()) { + appendWriter.Write("Another log entry\n"); + appendWriter.Flush(); +} + +// 使用 String 写入 +Containers::String content = "Content written from String"; +FileWriter writer3("data.txt"); +writer3.Write(content); +``` + +## 相关文档 + +- [Core 模块总览](../core.md) - 返回模块总览 +- [Logger](../../debug/logger/logger.md) - 日志系统 +- [FileLogSink](../../debug/filelogsink/filelogsink.md) - 文件日志输出 diff --git a/docs/api/core/refcounted/AddRef.md b/docs/api/core/refcounted/AddRef.md new file mode 100644 index 0000000..8e1972b --- /dev/null +++ b/docs/api/core/refcounted/AddRef.md @@ -0,0 +1,40 @@ +# RefCounted::AddRef + +```cpp +void AddRef(); +``` + +增加引用计数。 + +**描述** + +原子地增加引用计数。在复制 `RefCounted` 指针或传递引用时调用此方法。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +class MyObject : public RefCounted { +public: + void DoSomething() { /* ... */ } +}; + +// 创建对象(构造时 refCount = 1) +MyObject* obj = new MyObject(); + +// 手动增加引用 +obj->AddRef(); // refCount = 2 +obj->AddRef(); // refCount = 3 + +// 需要释放额外的引用 +obj->Release(); // refCount = 2 +obj->Release(); // refCount = 1 +``` + +## 相关文档 + +- [RefCounted 总览](refcounted.md) - 返回类总览 +- [Release](Release.md) - 减少引用计数 diff --git a/docs/api/core/refcounted/GetRefCount.md b/docs/api/core/refcounted/GetRefCount.md new file mode 100644 index 0000000..16c69a0 --- /dev/null +++ b/docs/api/core/refcounted/GetRefCount.md @@ -0,0 +1,43 @@ +# RefCounted::GetRefCount + +```cpp +uint32_t GetRefCount() const; +``` + +获取当前引用计数。 + +**描述** + +返回当前的引用计数值。由于使用 `std::atomic` 实现,因此是线程安全的。 + +**返回:** `uint32_t` - 当前引用计数 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +class MyObject : public RefCounted { +public: + void Debug() { + printf("RefCount: %u\n", GetRefCount()); + } +}; + +MyObject* obj = new MyObject(); +printf("After create: %u\n", obj->GetRefCount()); // 1 + +obj->AddRef(); +printf("After AddRef: %u\n", obj->GetRefCount()); // 2 + +obj->Release(); +printf("After Release: %u\n", obj->GetRefCount()); // 1 +``` + +## 相关文档 + +- [RefCounted 总览](refcounted.md) - 返回类总览 +- [AddRef](AddRef.md) - 增加引用计数 +- [Release](Release.md) - 减少引用计数 diff --git a/docs/api/core/refcounted/Release.md b/docs/api/core/refcounted/Release.md new file mode 100644 index 0000000..a3ac676 --- /dev/null +++ b/docs/api/core/refcounted/Release.md @@ -0,0 +1,39 @@ +# RefCounted::Release + +```cpp +void Release(); +``` + +减少引用计数。 + +**描述** + +原子地减少引用计数。当引用计数归零时,对象会自动 `delete this`。这是实现自动内存管理的关键方法。 + +**复杂度:** O(1)(归零时为 O(n),n 为对象大小) + +**示例:** + +```cpp +#include + +class MyObject : public RefCounted { +public: + void DoSomething() { /* ... */ } +}; + +// 创建对象(构造时 refCount = 1) +MyObject* obj = new MyObject(); + +// 手动增加引用 +obj->AddRef(); // refCount = 2 + +// 释放引用 +obj->Release(); // refCount = 1 +obj->Release(); // refCount = 0, 对象被自动 delete +``` + +## 相关文档 + +- [RefCounted 总览](refcounted.md) - 返回类总览 +- [AddRef](AddRef.md) - 增加引用计数 diff --git a/docs/api/core/refcounted/refcounted.md b/docs/api/core/refcounted/refcounted.md new file mode 100644 index 0000000..947bf28 --- /dev/null +++ b/docs/api/core/refcounted/refcounted.md @@ -0,0 +1,44 @@ +# RefCounted + +**命名空间**: `XCEngine::Core` + +**类型**: `class` + +**描述**: 引用计数基类,提供线程安全的引用计数生命周期管理。 + +## 概述 + +`RefCounted` 是一个简单的引用计数基类。当引用计数归零时,对象会自动删除。它提供了 `AddRef` 和 `Release` 方法,线程安全地管理引用计数。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `RefCounted()` | 构造函数,初始引用计数为 1 | +| `virtual ~RefCounted()` | 虚析构函数 | +| [`AddRef`](AddRef.md) | 增加引用计数 | +| [`Release`](Release.md) | 减少引用计数(归零时自动 delete this) | +| [`GetRefCount`](GetRefCount.md) | 获取当前引用计数 | + +## 使用示例 + +```cpp +class MyObject : public RefCounted { +public: + MyObject() { /* ... */ } + ~MyObject() { /* ... */ } + + void DoSomething() { /* ... */ } +}; + +// 使用 +MyObject* obj = new MyObject(); // refCount = 1 +obj->AddRef(); // refCount = 2 +obj->Release(); // refCount = 1 +obj->Release(); // refCount = 0, 自动 delete +``` + +## 相关文档 + +- [Core 模块总览](../core.md) - 返回模块总览 +- [SmartPtr](../smartptr/smartptr.md) - 智能指针 diff --git a/docs/api/core/smartptr/MakeRef.md b/docs/api/core/smartptr/MakeRef.md new file mode 100644 index 0000000..a361213 --- /dev/null +++ b/docs/api/core/smartptr/MakeRef.md @@ -0,0 +1,51 @@ +# SmartPtr::MakeRef + +```cpp +template +Ref MakeRef(Args&&... args); +``` + +创建共享指针的工厂函数。 + +**描述** + +`MakeRef` 是创建 `Ref` 的工厂函数,使用完美转发将参数传递给 `T` 的构造函数。相比直接使用 `std::make_shared`,代码更简洁。 + +**模板参数:** +- `T` - 被创建对象的类型 +- `Args` - 构造函数的参数类型 + +**参数:** +- `args` - 转发给 T 构造函数的参数 + +**返回:** `Ref` - 新创建的共享指针 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +class MyClass { +public: + MyClass(int a, int b) : m_a(a), m_b(b) {} + int GetSum() const { return m_a + m_b; } +private: + int m_a, m_b; +}; + +// 创建共享指针 +Core::Ref ref = Core::MakeRef(10, 20); +printf("Sum: %d\n", ref->GetSum()); + +// 使用 lambda +Core::Ref> callback = Core::MakeRef>([]() { + printf("Callback invoked!\n"); +}); +``` + +## 相关文档 + +- [SmartPtr 总览](smartptr.md) - 返回类总览 +- [Ref](Ref.md) - Ref 类型说明 diff --git a/docs/api/core/smartptr/MakeUnique.md b/docs/api/core/smartptr/MakeUnique.md new file mode 100644 index 0000000..699012e --- /dev/null +++ b/docs/api/core/smartptr/MakeUnique.md @@ -0,0 +1,49 @@ +# SmartPtr::MakeUnique + +```cpp +template +UniqueRef MakeUnique(Args&&... args); +``` + +创建独占指针的工厂函数。 + +**描述** + +`MakeUnique` 是创建 `UniqueRef` 的工厂函数,使用完美转发将参数传递给 `T` 的构造函数。相比直接使用 `std::make_unique`,代码更简洁。 + +**模板参数:** +- `T` - 被创建对象的类型 +- `Args` - 构造函数的参数类型 + +**参数:** +- `args` - 转发给 T 构造函数的参数 + +**返回:** `UniqueRef` - 新创建的独占指针 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +class MyClass { +public: + MyClass(int value) : m_value(value) {} + int GetValue() const { return m_value; } +private: + int m_value; +}; + +// 创建独占指针 +Core::UniqueRef unique = Core::MakeUnique(42); +printf("Value: %d\n", unique->GetValue()); + +// 转移所有权 +Core::UniqueRef moved = Core::MakeUnique(100); +``` + +## 相关文档 + +- [SmartPtr 总览](smartptr.md) - 返回类总览 +- [UniqueRef](UniqueRef.md) - UniqueRef 类型说明 diff --git a/docs/api/core/smartptr/Ref.md b/docs/api/core/smartptr/Ref.md new file mode 100644 index 0000000..1f7721e --- /dev/null +++ b/docs/api/core/smartptr/Ref.md @@ -0,0 +1,40 @@ +# SmartPtr::Ref + +```cpp +template +using Ref = std::shared_ptr; +``` + +共享引用智能指针类型别名。 + +**描述** + +`Ref` 是 `std::shared_ptr` 的类型别名,提供共享所有权的智能指针。多个 `Ref` 可以指向同一个对象,通过引用计数管理生命周期。当最后一个 `Ref` 被销毁时,对象会被自动删除。 + +**模板参数:** +- `T` - 被托管对象的类型 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +class MyClass { +public: + void DoSomething() { /* ... */ } +}; + +Core::Ref ref1 = Core::MakeRef(); +Core::Ref ref2 = ref1; // 共享所有权 + +if (ref1) { + ref1->DoSomething(); +} +``` + +## 相关文档 + +- [SmartPtr 总览](smartptr.md) - 返回类总览 +- [MakeRef](MakeRef.md) - 创建 Ref 的工厂函数 diff --git a/docs/api/core/smartptr/UniqueRef.md b/docs/api/core/smartptr/UniqueRef.md new file mode 100644 index 0000000..c25dea4 --- /dev/null +++ b/docs/api/core/smartptr/UniqueRef.md @@ -0,0 +1,46 @@ +# SmartPtr::UniqueRef + +```cpp +template +using UniqueRef = std::unique_ptr; +``` + +独占所有权的智能指针类型别名。 + +**描述** + +`UniqueRef` 是 `std::unique_ptr` 的类型别名,提供独占所有权的智能指针。每个对象只能有一个 `UniqueRef` 持有,当 `UniqueRef` 被销毁时,对象会被自动删除。不能复制,只能移动。 + +**模板参数:** +- `T` - 被托管对象的类型 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +class MyClass { +public: + void DoSomething() { /* ... */ } +}; + +Core::UniqueRef unique = Core::MakeUnique(); + +if (unique) { + unique->DoSomething(); +} + +// 自定义删除器 +Core::UniqueRef + file(fopen("test.txt", "r"), &fclose); + +// 转移所有权 +Core::UniqueRef moved = std::move(unique); +``` + +## 相关文档 + +- [SmartPtr 总览](smartptr.md) - 返回类总览 +- [MakeUnique](MakeUnique.md) - 创建 UniqueRef 的工厂函数 diff --git a/docs/api/core/smartptr/smartptr.md b/docs/api/core/smartptr/smartptr.md new file mode 100644 index 0000000..f87ee2d --- /dev/null +++ b/docs/api/core/smartptr/smartptr.md @@ -0,0 +1,64 @@ +# SmartPtr + +**命名空间**: `XCEngine::Core` + +**类型**: `header-only` + +**描述**: 智能指针类型别名和工厂函数,提供 `std::shared_ptr` 和 `std::unique_ptr` 的简化接口。 + +## 概述 + +`Core::SmartPtr` 提供了 `std::shared_ptr` 和 `std::unique_ptr` 的类型别名和工厂函数,使智能指针的使用更加简洁。 + +## 类型别名 + +| 别名 | 底层类型 | 描述 | +|------|----------|------| +| `Core::Ref` | `std::shared_ptr` | 共享引用智能指针 | +| `Core::UniqueRef` | `std::unique_ptr` | 独占所有权的智能指针 | + +## 工厂函数 + +| 函数 | 返回值 | 描述 | +|------|--------|------| +| `Core::MakeRef(Args&&... args)` | `Ref` | 创建共享指针 | +| `Core::MakeUnique(Args&&... args)` | `UniqueRef` | 创建独占指针 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Ref`](Ref.md) | `std::shared_ptr` 类型别名 | +| [`UniqueRef`](UniqueRef.md) | `std::unique_ptr` 类型别名 | +| [`MakeRef`](MakeRef.md) | 创建共享指针的工厂函数 | +| [`MakeUnique`](MakeUnique.md) | 创建独占指针的工厂函数 | + +## 使用示例 + +```cpp +#include + +// 使用 Ref(共享指针) +Core::Ref ref = Core::MakeRef(arg1, arg2); + +// 使用 UniqueRef(独占指针) +Core::UniqueRef unique = Core::MakeUnique(); + +// 传递所有权 +Core::Ref ref2 = ref; // 引用计数 +1 + +// 检查有效性 +if (ref) { + ref->DoSomething(); +} + +// 自定义删除器 +Core::UniqueRef + file(fopen("test.txt", "r"), &fclose); +``` + +## 相关文档 + +- [Core 模块总览](../core.md) - 返回模块总览 +- [RefCounted](../refcounted/refcounted.md) - 引用计数基类 +- [Types](../types/types.md) - 类型别名 diff --git a/docs/api/core/types/byte.md b/docs/api/core/types/byte.md new file mode 100644 index 0000000..eff9330 --- /dev/null +++ b/docs/api/core/types/byte.md @@ -0,0 +1,30 @@ +# Types::byte + +```cpp +using byte = uint8_t; +``` + +字节类型别名,对应 `uint8_t` 类型。 + +**描述** + +`byte` 是 1 字节无符号整数类型,专门用于表示原始字节数据。语义上比 `uint8` 更清晰,适用于二进制数据、内存缓冲区等场景。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +Core::byte header[4] = {0x00, 0x01, 0x02, 0x03}; +Core::byte flags = 0b11001010; + +// 内存缓冲区 +Core::byte* buffer = new Core::byte[1024]; +``` + +## 相关文档 + +- [Types 总览](types.md) - 返回类型总览 +- [uint8](uint8.md) - 底层类型 diff --git a/docs/api/core/types/int16.md b/docs/api/core/types/int16.md new file mode 100644 index 0000000..fc666ed --- /dev/null +++ b/docs/api/core/types/int16.md @@ -0,0 +1,27 @@ +# Types::int16 + +```cpp +using int16 = int16_t; +``` + +16位有符号整数类型别名,对应 C++ 标准库的 `int16_t` 类型。 + +**描述** + +`int16` 是 16 位(2 字节)有符号整数类型,范围为 -32,768 到 32,767。该类型别名确保跨平台一致性。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +Core::int16 shortValue = -10000; +Core::int16 maxValue = 32767; +``` + +## 相关文档 + +- [Types 总览](types.md) - 返回类型总览 +- [uint16](uint16.md) - 对应的无符号类型 diff --git a/docs/api/core/types/int32.md b/docs/api/core/types/int32.md new file mode 100644 index 0000000..9c4aeb3 --- /dev/null +++ b/docs/api/core/types/int32.md @@ -0,0 +1,30 @@ +# Types::int32 + +```cpp +using int32 = int32_t; +``` + +32位有符号整数类型别名,对应 C++ 标准库的 `int32_t` 类型。 + +**描述** + +`int32` 是 32 位(4 字节)有符号整数类型,范围为 -2,147,483,648 到 2,147,483,647。该类型别名确保跨平台一致性,是最常用的整数类型。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +Core::int32 score = 1000000; +Core::int32 negative = -500000; + +// 函数参数类型 +void SetHealth(Core::int32 health); +``` + +## 相关文档 + +- [Types 总览](types.md) - 返回类型总览 +- [uint32](uint32.md) - 对应的无符号类型 diff --git a/docs/api/core/types/int64.md b/docs/api/core/types/int64.md new file mode 100644 index 0000000..7d80c40 --- /dev/null +++ b/docs/api/core/types/int64.md @@ -0,0 +1,30 @@ +# Types::int64 + +```cpp +using int64 = int64_t; +``` + +64位有符号整数类型别名,对应 C++ 标准库的 `int64_t` 类型。 + +**描述** + +`int64` 是 64 位(8 字节)有符号整数类型,范围为 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807。该类型别名用于需要大范围整数的场景,如时间戳、大文件大小等。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +Core::int64 largeNumber = 9223372036854775807LL; +Core::int64 fileSize = 1099511627776LL; // 1TB + +// 时间戳(毫秒) +Core::int64 timestamp = 1700000000000LL; +``` + +## 相关文档 + +- [Types 总览](types.md) - 返回类型总览 +- [uint64](uint64.md) - 对应的无符号类型 diff --git a/docs/api/core/types/int8.md b/docs/api/core/types/int8.md new file mode 100644 index 0000000..348d020 --- /dev/null +++ b/docs/api/core/types/int8.md @@ -0,0 +1,28 @@ +# Types::int8 + +```cpp +using int8 = int8_t; +``` + +8位有符号整数类型别名,对应 C++ 标准库的 `int8_t` 类型。 + +**描述** + +`int8` 是 8 位(1 字节)有符号整数类型,范围为 -128 到 127。该类型别名确保跨平台一致性。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +Core::int8 signedByte = -50; +Core::int8 maxValue = 127; +Core::int8 minValue = -128; +``` + +## 相关文档 + +- [Types 总览](types.md) - 返回类型总览 +- [uint8](uint8.md) - 对应的无符号类型 diff --git a/docs/api/core/types/types.md b/docs/api/core/types/types.md new file mode 100644 index 0000000..645077f --- /dev/null +++ b/docs/api/core/types/types.md @@ -0,0 +1,63 @@ +# Types + +**命名空间**: `XCEngine::Core` + +**类型**: `header` (type aliases) + +**头文件**: `XCEngine/Core/Types.h` + +**描述**: 基础类型别名定义,提供跨平台一致的基础类型名称。 + +## 概述 + +`Types.h` 定义了一组类型别名,简化了标准库类型的使用,并提供跨平台一致性。 + +## 类型别名 + +| 别名 | 实际类型 | 描述 | +|------|----------|------| +| `int8` | `int8_t` | 8位有符号整数 | +| `int16` | `int16_t` | 16位有符号整数 | +| `int32` | `int32_t` | 32位有符号整数 | +| `int64` | `int64_t` | 64位有符号整数 | +| `uint8` | `uint8_t` | 8位无符号整数 | +| `uint16` | `uint16_t` | 16位无符号整数 | +| `uint32` | `uint32_t` | 32位无符号整数 | +| `uint64` | `uint64_t` | 64位无符号整数 | +| `byte` | `uint8_t` | 字节类型 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`int8`](int8.md) | 8位有符号整数类型别名 | +| [`int16`](int16.md) | 16位有符号整数类型别名 | +| [`int32`](int32.md) | 32位有符号整数类型别名 | +| [`int64`](int64.md) | 64位有符号整数类型别名 | +| [`uint8`](uint8.md) | 8位无符号整数类型别名 | +| [`uint16`](uint16.md) | 16位无符号整数类型别名 | +| [`uint32`](uint32.md) | 32位无符号整数类型别名 | +| [`uint64`](uint64.md) | 64位无符号整数类型别名 | +| [`byte`](byte.md) | 字节类型别名 | + +## 使用示例 + +```cpp +#include + +// 使用类型别名 +Core::int32 count = 100; +Core::uint64 id = 1234567890; +Core::byte flags = 0xFF; + +// 数组定义 +Core::uint8 buffer[1024]; + +// 函数参数 +void ProcessData(Core::uint32 size, const Core::int8* data); +``` + +## 相关文档 + +- [Core 模块总览](../core.md) - 返回模块总览 +- [SmartPtr](../smartptr/smartptr.md) - 智能指针 diff --git a/docs/api/core/types/uint16.md b/docs/api/core/types/uint16.md new file mode 100644 index 0000000..3b4a42b --- /dev/null +++ b/docs/api/core/types/uint16.md @@ -0,0 +1,30 @@ +# Types::uint16 + +```cpp +using uint16 = uint16_t; +``` + +16位无符号整数类型别名,对应 C++ 标准库的 `uint16_t` 类型。 + +**描述** + +`uint16` 是 16 位(2 字节)无符号整数类型,范围为 0 到 65,535。常用于 Unicode 字符、端口号等场景。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +Core::uint16 port = 8080; +Core::uint16 maxConnections = 65535; + +// Unicode 字符 +Core::uint16 unicodeChar = 0x4E2D; +``` + +## 相关文档 + +- [Types 总览](types.md) - 返回类型总览 +- [int16](int16.md) - 对应的有符号类型 diff --git a/docs/api/core/types/uint32.md b/docs/api/core/types/uint32.md new file mode 100644 index 0000000..4caae08 --- /dev/null +++ b/docs/api/core/types/uint32.md @@ -0,0 +1,30 @@ +# Types::uint32 + +```cpp +using uint32 = uint32_t; +``` + +32位无符号整数类型别名,对应 C++ 标准库的 `uint32_t` 类型。 + +**描述** + +`uint32` 是 32 位(4 字节)无符号整数类型,范围为 0 到 4,294,967,295。常用于 ID、计数、大小等场景。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +Core::uint32 entityId = 1000000; +Core::uint32 maxItems = 4294967295U; + +// 数组大小 +Core::uint32 arraySize = 1000; +``` + +## 相关文档 + +- [Types 总览](types.md) - 返回类型总览 +- [int32](int32.md) - 对应的有符号类型 diff --git a/docs/api/core/types/uint64.md b/docs/api/core/types/uint64.md new file mode 100644 index 0000000..ab23116 --- /dev/null +++ b/docs/api/core/types/uint64.md @@ -0,0 +1,30 @@ +# Types::uint64 + +```cpp +using uint64 = uint64_t; +``` + +64位无符号整数类型别名,对应 C++ 标准库的 `uint64_t` 类型。 + +**描述** + +`uint64` 是 64 位(8 字节)无符号整数类型,范围为 0 到 18,446,744,073,709,551,615。用于需要极大整数范围的场景,如大文件大小、精确时间等。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +Core::uint64 largeFileSize = 1099511627776ULL; // 1TB +Core::uint64 maxValue = 18446744073709551615ULL; + +// 高精度时间戳(微秒) +Core::uint64 microseconds = 1700000000000000ULL; +``` + +## 相关文档 + +- [Types 总览](types.md) - 返回类型总览 +- [int64](int64.md) - 对应的有符号类型 diff --git a/docs/api/core/types/uint8.md b/docs/api/core/types/uint8.md new file mode 100644 index 0000000..6b55bc5 --- /dev/null +++ b/docs/api/core/types/uint8.md @@ -0,0 +1,30 @@ +# Types::uint8 + +```cpp +using uint8 = uint8_t; +``` + +8位无符号整数类型别名,对应 C++ 标准库的 `uint8_t` 类型。 + +**描述** + +`uint8` 是 8 位(1 字节)无符号整数类型,范围为 0 到 255。常用于字节数据、颜色分量(RGB)等场景。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +Core::uint8 flags = 0xFF; +Core::uint8 red = 255; + +// 字节数组 +Core::uint8 buffer[256]; +``` + +## 相关文档 + +- [Types 总览](types.md) - 返回类型总览 +- [int8](int8.md) - 对应的有符号类型 diff --git a/docs/api/debug/consolelogsink/consolelogsink.md b/docs/api/debug/consolelogsink/consolelogsink.md new file mode 100644 index 0000000..8a43dd2 --- /dev/null +++ b/docs/api/debug/consolelogsink/consolelogsink.md @@ -0,0 +1,21 @@ +# ConsoleLogSink::ConsoleLogSink + +```cpp +ConsoleLogSink() +``` + +默认构造函数。创建一个 `ConsoleLogSink` 实例,默认启用彩色输出,最小日志级别为 `Verbose`。 + +**复杂度:** O(1) + +**示例:** + +```cpp +auto sink = std::make_unique(); +XCEngine::Debug::Logger::Get().AddSink(std::move(sink)); +``` + +## 相关文档 + +- [ConsoleLogSink 总览](overview.md) - 返回类总览 +- [Debug 模块总览](../debug.md) - 返回模块总览 diff --git a/docs/api/debug/consolelogsink/flush.md b/docs/api/debug/consolelogsink/flush.md new file mode 100644 index 0000000..bccfde9 --- /dev/null +++ b/docs/api/debug/consolelogsink/flush.md @@ -0,0 +1,22 @@ +# ConsoleLogSink::Flush + +```cpp +void Flush() override +``` + +刷新标准输出流(stdout),调用 `fflush(stdout)` 确保所有待输出的日志内容立即显示在控制台上。 + +**复杂度:** O(1) + +**示例:** + +```cpp +auto sink = std::make_unique(); +XCEngine::Debug::Logger::Get().AddSink(std::move(sink)); +// 在程序异常退出前确保日志已输出 +XCEngine::Debug::Logger::Get().Flush(); +``` + +## 相关文档 + +- [ConsoleLogSink 总览](consolelogsink.md) - 返回类总览 diff --git a/docs/api/debug/consolelogsink/log.md b/docs/api/debug/consolelogsink/log.md new file mode 100644 index 0000000..44f6af5 --- /dev/null +++ b/docs/api/debug/consolelogsink/log.md @@ -0,0 +1,25 @@ +# ConsoleLogSink::Log + +```cpp +void Log(const LogEntry& entry) override +``` + +将日志输出到控制台。根据 `LogEntry` 的级别和分类格式化输出内容,并根据 `m_colorOutput` 设置决定是否使用 Windows 控制台颜色 API。如果日志级别低于设置的最小级别,则不输出。 + +**参数:** +- `entry` - 日志条目 + +**复杂度:** O(1) + +**示例:** + +```cpp +auto sink = std::make_unique(); +// Log 方法由 Logger 在内部调用,用户无需直接调用 +XCEngine::Debug::Logger::Get().AddSink(std::move(sink)); +XCEngine::Debug::Logger::Get().Info(XCEngine::Debug::LogCategory::General, "Hello console"); +``` + +## 相关文档 + +- [ConsoleLogSink 总览](consolelogsink.md) - 返回类总览 diff --git a/docs/api/debug/consolelogsink/overview.md b/docs/api/debug/consolelogsink/overview.md new file mode 100644 index 0000000..f54f8ce --- /dev/null +++ b/docs/api/debug/consolelogsink/overview.md @@ -0,0 +1,41 @@ +# ConsoleLogSink + +**命名空间**: `XCEngine::Debug` + +**类型**: `class` + +**头文件**: `XCEngine/Debug/ConsoleLogSink.h` + +**描述**: 控制台日志输出目标,将日志输出到标准输出流。 + +## 概述 + +`ConsoleLogSink` 是日志系统的控制台输出实现。它将日志条目输出到标准输出流(stdout),支持彩色输出和日志级别过滤。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `ConsoleLogSink()` | [构造函数](consolelogsink.md) | +| `~ConsoleLogSink()` | [析构函数](~consolelogsink.md) | +| `void Log(const LogEntry& entry)` | [输出日志到控制台](log.md) | +| `void Flush()` | [刷新输出流](flush.md) | +| `void SetColorOutput(bool enable)` | [设置彩色输出](setcoloroutput.md) | +| `void SetMinimumLevel(LogLevel level)` | [设置最小日志级别](setminimumlevel.md) | + +## 使用示例 + +```cpp +#include + +auto sink = std::make_unique(); +sink->SetColorOutput(true); +sink->SetMinimumLevel(XCEngine::Debug::LogLevel::Warning); +XCEngine::Debug::Logger::Get().AddSink(std::move(sink)); +``` + +## 相关文档 + +- [Debug 模块总览](../debug.md) - 返回模块总览 +- [Logger](../logger/logger.md) - 日志记录器 +- [ILogSink](../ilogsink/ilogsink.md) - 日志输出接口 diff --git a/docs/api/debug/consolelogsink/setcoloroutput.md b/docs/api/debug/consolelogsink/setcoloroutput.md new file mode 100644 index 0000000..1bea375 --- /dev/null +++ b/docs/api/debug/consolelogsink/setcoloroutput.md @@ -0,0 +1,24 @@ +# ConsoleLogSink::SetColorOutput + +```cpp +void SetColorOutput(bool enable) +``` + +启用或禁用控制台彩色输出。启用后,不同日志级别使用 Windows 控制台颜色 API 输出,便于快速区分日志类型。 + +**参数:** +- `enable` - true 启用彩色输出,false 禁用 + +**复杂度:** O(1) + +**示例:** + +```cpp +auto sink = std::make_unique(); +sink->SetColorOutput(false); // 禁用颜色(适合日志文件或 CI 环境) +XCEngine::Debug::Logger::Get().AddSink(std::move(sink)); +``` + +## 相关文档 + +- [ConsoleLogSink 总览](consolelogsink.md) - 返回类总览 diff --git a/docs/api/debug/consolelogsink/setminimumlevel.md b/docs/api/debug/consolelogsink/setminimumlevel.md new file mode 100644 index 0000000..8b64fa1 --- /dev/null +++ b/docs/api/debug/consolelogsink/setminimumlevel.md @@ -0,0 +1,24 @@ +# ConsoleLogSink::SetMinimumLevel + +```cpp +void SetMinimumLevel(LogLevel level) +``` + +设置该 Sink 的最小输出级别。此设置仅影响当前 Sink,不会影响 Logger 的全局级别过滤。 + +**参数:** +- `level` - 最小日志级别 + +**复杂度:** O(1) + +**示例:** + +```cpp +auto sink = std::make_unique(); +sink->SetMinimumLevel(XCEngine::Debug::LogLevel::Warning); // 控制台只显示警告及以上 +XCEngine::Debug::Logger::Get().AddSink(std::move(sink)); +``` + +## 相关文档 + +- [ConsoleLogSink 总览](consolelogsink.md) - 返回类总览 diff --git a/docs/api/debug/consolelogsink/~consolelogsink.md b/docs/api/debug/consolelogsink/~consolelogsink.md new file mode 100644 index 0000000..802c70e --- /dev/null +++ b/docs/api/debug/consolelogsink/~consolelogsink.md @@ -0,0 +1,13 @@ +# ConsoleLogSink::~ConsoleLogSink + +```cpp +~ConsoleLogSink() override +``` + +析构函数。销毁 `ConsoleLogSink` 实例,释放相关资源。 + +**复杂度:** O(1) + +## 相关文档 + +- [ConsoleLogSink 总览](consolelogsink.md) - 返回类总览 diff --git a/docs/api/debug/debug.md b/docs/api/debug/debug.md new file mode 100644 index 0000000..3ade25d --- /dev/null +++ b/docs/api/debug/debug.md @@ -0,0 +1,86 @@ +# Debug 模块概览 + +**命名空间**: `XCEngine::Debug` + +**类型**: `module` + +**描述**: XCEngine 的调试和日志模块,提供日志记录和性能分析功能。 + +## 概述 + +Debug 模块提供了一套完整的调试工具,包括日志系统和性能分析器。 + +## 模块内容 + +### 日志系统 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [Logger](logger/logger.md) | `Logger.h` | 日志记录器 | +| [ILogSink](ilogsink/ilogsink.md) | `ILogSink.h` | 日志输出接口 | +| [ConsoleLogSink](consolelogsink/consolelogsink.md) | `ConsoleLogSink.h` | 控制台输出 | +| [FileLogSink](filelogsink/filelogsink.md) | `FileLogSink.h` | 文件输出 | +| [LogLevel](loglevel/loglevel.md) | `LogLevel.h` | 日志级别枚举 | +| [LogCategory](logcategory/logcategory.md) | `LogCategory.h` | 日志分类枚举 | +| [LogEntry](logentry/logentry.md) | `LogEntry.h` | 日志条目结构 | + +### 性能分析 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [Profiler](profiler/profiler.md) | `Profiler.h` | 性能分析器 | + +## 日志级别 + +| 级别 | 描述 | +|------|------| +| `Verbose` | 详细调试信息 | +| `Debug` | 调试信息 | +| `Info` | 一般信息 | +| `Warning` | 警告信息 | +| `Error` | 错误信息 | +| `Fatal` | 致命错误 | + +## 日志分类 + +| 分类 | 描述 | +|------|------| +| `General` | 通用 | +| `Rendering` | 渲染 | +| `Physics` | 物理 | +| `Audio` | 音频 | +| `Scripting` | 脚本 | +| `Network` | 网络 | +| `Memory` | 内存 | +| `Threading` | 线程 | +| `FileSystem` | 文件系统 | +| `Custom` | 自定义 | + +## 使用示例 + +```cpp +#include + +// 初始化日志系统 +Logger::Get().Initialize(); +Logger::Get().AddSink(std::make_unique()); +Logger::Get().AddSink(std::make_unique("app.log")); + +// 设置日志级别 +Logger::Get().SetMinimumLevel(LogLevel::Debug); + +// 记录日志 +XE_LOG(LogCategory::Rendering, LogLevel::Info, "Render started"); + +// 使用宏记录日志 +if (condition) { + XE_LOG(LogCategory::General, LogLevel::Error, "Something went wrong"); +} + +// 使用断言 +XE_ASSERT(ptr != nullptr, "Pointer must not be null"); +``` + +## 相关文档 + +- [Profiler](profiler/profiler.md) - 性能分析器 diff --git a/docs/api/debug/filelogsink/construct.md b/docs/api/debug/filelogsink/construct.md new file mode 100644 index 0000000..db32c9a --- /dev/null +++ b/docs/api/debug/filelogsink/construct.md @@ -0,0 +1,24 @@ +# FileLogSink::FileLogSink + +```cpp +FileLogSink(const Containers::String& filePath) +``` + +构造函数,打开指定路径的文件用于日志写入。如果文件已存在,则追加写入;如果不存在,则创建新文件。 + +**参数:** +- `filePath` - 日志文件路径 + +**复杂度:** O(1) + +**示例:** + +```cpp +auto fileSink = std::make_unique("logs/engine.log"); +XCEngine::Debug::Logger::Get().AddSink(std::move(fileSink)); +``` + +## 相关文档 + +- [FileLogSink 总览](filelogsink.md) - 返回类总览 +- [Debug 模块总览](../debug.md) - 返回模块总览 diff --git a/docs/api/debug/filelogsink/filelogsink.md b/docs/api/debug/filelogsink/filelogsink.md new file mode 100644 index 0000000..a3379d4 --- /dev/null +++ b/docs/api/debug/filelogsink/filelogsink.md @@ -0,0 +1,37 @@ +# FileLogSink + +**命名空间**: `XCEngine::Debug` + +**类型**: `class` + +**头文件**: `XCEngine/Debug/FileLogSink.h` + +**描述**: 文件日志输出目标,将日志写入到指定文件。 + +## 概述 + +`FileLogSink` 是日志系统的文件输出实现。它将日志条目写入到指定的文件,支持追加写入模式。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `FileLogSink(const Containers::String& filePath)` | [构造函数](construct.md) | +| `~FileLogSink()` | [析构函数](~filelogsink.md) | +| `void Log(const LogEntry& entry)` | [输出日志到文件](log.md) | +| `void Flush()` | [刷新缓冲区](flush.md) | + +## 使用示例 + +```cpp +#include + +auto fileSink = std::make_unique("logs/app.log"); +XCEngine::Debug::Logger::Get().AddSink(std::move(fileSink)); +``` + +## 相关文档 + +- [Debug 模块总览](../debug.md) - 返回模块总览 +- [Logger](../logger/logger.md) - 日志记录器 +- [ILogSink](../ilogsink/ilogsink.md) - 日志输出接口 diff --git a/docs/api/debug/filelogsink/flush.md b/docs/api/debug/filelogsink/flush.md new file mode 100644 index 0000000..7dd078a --- /dev/null +++ b/docs/api/debug/filelogsink/flush.md @@ -0,0 +1,24 @@ +# FileLogSink::Flush + +```cpp +void Flush() override +``` + +刷新文件缓冲区,调用底层 `FileWriter` 的 flush 方法确保所有待写入的日志数据已实际写入磁盘。 + +**复杂度:** O(1) + +**示例:** + +```cpp +auto fileSink = std::make_unique("logs/app.log"); +XCEngine::Debug::Logger::Get().AddSink(std::move(fileSink)); +// 关键操作后立即刷新 +XCEngine::Debug::Logger::Get().Info(XCEngine::Debug::LogCategory::General, "Checkpoint saved"); +// 确保写入磁盘 +XCEngine::Debug::Logger::Get().Flush(); +``` + +## 相关文档 + +- [FileLogSink 总览](filelogsink.md) - 返回类总览 diff --git a/docs/api/debug/filelogsink/log.md b/docs/api/debug/filelogsink/log.md new file mode 100644 index 0000000..91563a9 --- /dev/null +++ b/docs/api/debug/filelogsink/log.md @@ -0,0 +1,25 @@ +# FileLogSink::Log + +```cpp +void Log(const LogEntry& entry) override +``` + +将日志条目追加写入文件。根据 `LogEntry` 的各字段格式化日志行,包括时间戳、级别、分类、消息,并追加到文件末尾。 + +**参数:** +- `entry` - 日志条目 + +**复杂度:** O(m),m 为消息长度 + +**示例:** + +```cpp +auto fileSink = std::make_unique("logs/app.log"); +XCEngine::Debug::Logger::Get().AddSink(std::move(fileSink)); +// Log 方法由 Logger 在内部调用 +XCEngine::Debug::Logger::Get().Error(XCEngine::Debug::LogCategory::FileSystem, "File not found"); +``` + +## 相关文档 + +- [FileLogSink 总览](filelogsink.md) - 返回类总览 diff --git a/docs/api/debug/filelogsink/~filelogsink.md b/docs/api/debug/filelogsink/~filelogsink.md new file mode 100644 index 0000000..17d3205 --- /dev/null +++ b/docs/api/debug/filelogsink/~filelogsink.md @@ -0,0 +1,13 @@ +# FileLogSink::~FileLogSink + +```cpp +~FileLogSink() override +``` + +析构函数。销毁 `FileLogSink` 实例,调用 `Flush()` 确保所有日志数据写入文件,然后关闭文件句柄。 + +**复杂度:** O(1) + +## 相关文档 + +- [FileLogSink 总览](filelogsink.md) - 返回类总览 diff --git a/docs/api/debug/ilogsink/flush.md b/docs/api/debug/ilogsink/flush.md new file mode 100644 index 0000000..f088ee9 --- /dev/null +++ b/docs/api/debug/ilogsink/flush.md @@ -0,0 +1,32 @@ +# ILogSink::Flush + +```cpp +virtual void Flush() = 0 +``` + +刷新输出缓冲区,确保所有待写入的日志数据已实际写入目标介质。对于文件类 Sink,应调用底层文件系统的 flush;对于网络类 Sink,应发送缓冲区中的数据。 + +**复杂度:** O(1) + +**示例:** + +```cpp +class BufferedLogSink : public XCEngine::Debug::ILogSink { +private: + std::string m_buffer; +public: + void Log(const XCEngine::Debug::LogEntry& entry) override { + m_buffer += entry.message.CStr(); + m_buffer += "\n"; + } + void Flush() override { + // 将缓冲区数据写入目标 + writeToDestination(m_buffer); + m_buffer.clear(); + } +}; +``` + +## 相关文档 + +- [ILogSink 总览](ilogsink.md) - 返回类总览 diff --git a/docs/api/debug/ilogsink/ilogsink.md b/docs/api/debug/ilogsink/ilogsink.md new file mode 100644 index 0000000..839144f --- /dev/null +++ b/docs/api/debug/ilogsink/ilogsink.md @@ -0,0 +1,45 @@ +# ILogSink + +**命名空间**: `XCEngine::Debug` + +**类型**: `class` (abstract interface) + +**描述**: 日志输出槽抽象接口,定义日志输出的标准协议。 + +## 概述 + +`ILogSink` 是日志系统的输出抽象接口。用户可以实现此接口来创建自定义的日志输出方式,如网络输出、数据库存储等。`Logger` 通过多个 Sink 分发日志。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `virtual void Log(const LogEntry& entry) = 0` | [输出单条日志](log.md) | +| `virtual void Flush() = 0` | [刷新缓冲区,确保日志写入](flush.md) | + +## 使用示例 + +```cpp +class CustomLogSink : public ILogSink { +public: + void Log(const LogEntry& entry) override { + printf("[%s] %s: %s\n", + LogLevelToString(entry.level), + LogCategoryToString(entry.category), + entry.message.CStr()); + } + + void Flush() override { + fflush(stdout); + } +}; + +Logger::Get().AddSink(std::make_unique()); +``` + +## 相关文档 + +- [Debug 模块总览](../debug.md) - 返回模块总览 +- [Logger](../logger/logger.md) - 日志记录器 +- [ConsoleLogSink](../consolelogsink/consolelogsink.md) - 控制台输出 +- [FileLogSink](../filelogsink/filelogsink.md) - 文件输出 diff --git a/docs/api/debug/ilogsink/log.md b/docs/api/debug/ilogsink/log.md new file mode 100644 index 0000000..52aa91c --- /dev/null +++ b/docs/api/debug/ilogsink/log.md @@ -0,0 +1,29 @@ +# ILogSink::Log + +```cpp +virtual void Log(const LogEntry& entry) = 0 +``` + +输出单条日志到目标介质。`Logger` 在每次日志记录时调用此方法,将包含完整日志信息的 `LogEntry` 传入。派生类需要实现具体的输出逻辑。 + +**参数:** +- `entry` - 日志条目,包含级别、分类、消息、时间戳、线程 ID 等完整信息 + +**复杂度:** O(1) + +**示例:** + +```cpp +class NetworkLogSink : public XCEngine::Debug::ILogSink { +public: + void Log(const XCEngine::Debug::LogEntry& entry) override { + // 将日志发送到远程服务器 + sendToServer(entry.message.CStr()); + } + void Flush() override { } +}; +``` + +## 相关文档 + +- [ILogSink 总览](ilogsink.md) - 返回类总览 diff --git a/docs/api/debug/logcategory/logcategory.md b/docs/api/debug/logcategory/logcategory.md new file mode 100644 index 0000000..9932fa8 --- /dev/null +++ b/docs/api/debug/logcategory/logcategory.md @@ -0,0 +1,44 @@ +# LogCategory + +**命名空间**: `XCEngine::Debug` + +**类型**: `enum class` + +**描述**: 日志分类枚举,定义日志的来源模块。 + +## 概述 + +`LogCategory` 枚举定义了日志的分类,用于区分不同引擎模块的日志输出。 + +## 枚举值 + +| 值 | 说明 | +|----|------| +| `General` | 通用 | +| `Rendering` | 渲染 | +| `Physics` | 物理 | +| `Audio` | 音频 | +| `Scripting` | 脚本 | +| `Network` | 网络 | +| `Memory` | 内存 | +| `Threading` | 线程 | +| `FileSystem` | 文件系统 | +| `Custom` | 自定义 | + +## 辅助函数 + +| 函数 | 描述 | +|------|------| +| `const char* LogCategoryToString(LogCategory category)` | [将日志分类转换为字符串](logcategorytostring.md) | + +## 使用示例 + +```cpp +Logger::Get().SetCategoryEnabled(LogCategory::Network, false); +XE_LOG(LogCategory::Rendering, LogLevel::Info, "Draw call submitted"); +``` + +## 相关文档 + +- [Debug 模块总览](../debug.md) - 返回模块总览 +- [Logger](../logger/logger.md) - 日志记录器 diff --git a/docs/api/debug/logcategory/logcategorytostring.md b/docs/api/debug/logcategory/logcategorytostring.md new file mode 100644 index 0000000..01b9a97 --- /dev/null +++ b/docs/api/debug/logcategory/logcategorytostring.md @@ -0,0 +1,28 @@ +# LogCategoryToString + +```cpp +const char* LogCategoryToString(LogCategory category) +``` + +将 `LogCategory` 枚举值转换为可读字符串。 + +**参数:** +- `category` - 日志分类 + +**返回:** 对应分类的字符串("General", "Rendering", "Physics" 等) + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +XCEngine::Debug::LogCategory cat = XCEngine::Debug::LogCategory::Rendering; +const char* str = XCEngine::Debug::LogCategoryToString(cat); +// str == "Rendering" +``` + +## 相关文档 + +- [LogCategory 总览](logcategory.md) - 返回类总览 diff --git a/docs/api/debug/logentry/logentry.md b/docs/api/debug/logentry/logentry.md new file mode 100644 index 0000000..ae2e383 --- /dev/null +++ b/docs/api/debug/logentry/logentry.md @@ -0,0 +1,47 @@ +# LogEntry + +**命名空间**: `XCEngine::Debug` + +**类型**: `struct` + +**描述**: 日志条目结构体,包含单条日志的所有信息。 + +## 概述 + +`LogEntry` 是日志系统的核心数据结构,每次日志记录都生成一个 `LogEntry` 并分发给所有注册的 Sink。 + +## 结构体成员 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `level` | `LogLevel` | 日志级别 | +| `category` | `LogCategory` | 日志分类 | +| `message` | `Containers::String` | 日志消息内容 | +| `file` | `Containers::String` | 源代码文件路径 | +| `line` | `int32_t` | 源代码行号 | +| `function` | `Containers::String` | 函数名称 | +| `timestamp` | `uint64_t` | 时间戳(秒,Unix 时间戳) | +| `threadId` | `uint32_t` | 线程 ID | + +## 使用示例 + +```cpp +class MySink : public ILogSink { +public: + void Log(const LogEntry& entry) override { + printf("[%llu][%u] %s::%s: %s\n", + (unsigned long long)entry.timestamp, + (unsigned)entry.threadId, + LogCategoryToString(entry.category), + LogLevelToString(entry.level), + entry.message.CStr()); + } + void Flush() override { } +}; +``` + +## 相关文档 + +- [Debug 模块总览](../debug.md) - 返回模块总览 +- [ILogSink](../ilogsink/ilogsink.md) - 日志输出接口 +- [Logger](../logger/logger.md) - 日志记录器 diff --git a/docs/api/debug/logger/addsink.md b/docs/api/debug/logger/addsink.md new file mode 100644 index 0000000..e04eb90 --- /dev/null +++ b/docs/api/debug/logger/addsink.md @@ -0,0 +1,27 @@ +# Logger::AddSink + +```cpp +void AddSink(std::unique_ptr sink) +``` + +向日志系统添加一个输出目标(Sink)。Logger 持有 Sink 的所有权,传入的 `unique_ptr` 被移动到内部容器中。每次日志记录时,所有已注册的 Sink 的 `Log` 方法都会被调用。 + +**参数:** +- `sink` - 要添加的日志输出目标,使用 `std::unique_ptr` 包装 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +XCEngine::Debug::Logger::Get().Initialize(); +XCEngine::Debug::Logger::Get().AddSink(std::make_unique()); +XCEngine::Debug::Logger::Get().AddSink(std::make_unique("app.log")); +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 +- [ILogSink](../ilogsink/ilogsink.md) - 日志输出接口 diff --git a/docs/api/debug/logger/debug.md b/docs/api/debug/logger/debug.md new file mode 100644 index 0000000..cec3a9c --- /dev/null +++ b/docs/api/debug/logger/debug.md @@ -0,0 +1,30 @@ +# Logger::Debug + +```cpp +void Debug(LogCategory category, const Containers::String& message) +``` + +记录一条 Debug(1 级)日志。Debug 级别用于一般调试信息,比 Verbose 简洁但比 Info 详细。 + +**参数:** +- `category` - 日志分类 +- `message` - 日志消息内容 + +**返回:** 无 + +**复杂度:** O(n),n 为注册的 Sink 数量 + +**示例:** + +```cpp +#include + +XCEngine::Debug::Logger::Get().Debug( + XCEngine::Debug::LogCategory::Rendering, + "Draw call batch size: 512" +); +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 diff --git a/docs/api/debug/logger/error.md b/docs/api/debug/logger/error.md new file mode 100644 index 0000000..3dcdc5e --- /dev/null +++ b/docs/api/debug/logger/error.md @@ -0,0 +1,30 @@ +# Logger::Error + +```cpp +void Error(LogCategory category, const Containers::String& message) +``` + +记录一条 Error(4 级)日志。Error 级别用于表示程序执行中发生的错误,如文件读取失败、网络连接中断等。程序通常可以继续运行但功能可能受限。 + +**参数:** +- `category` - 日志分类 +- `message` - 日志消息内容 + +**返回:** 无 + +**复杂度:** O(n),n 为注册的 Sink 数量 + +**示例:** + +```cpp +#include + +XCEngine::Debug::Logger::Get().Error( + XCEngine::Debug::LogCategory::Network, + "Failed to connect to game server" +); +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 diff --git a/docs/api/debug/logger/fatal.md b/docs/api/debug/logger/fatal.md new file mode 100644 index 0000000..fa2fed0 --- /dev/null +++ b/docs/api/debug/logger/fatal.md @@ -0,0 +1,30 @@ +# Logger::Fatal + +```cpp +void Fatal(LogCategory category, const Containers::String& message) +``` + +记录一条 Fatal(5 级)日志。Fatal 级别用于表示不可恢复的严重错误,通常意味着程序即将终止。此方法可能在记录日志后触发程序中断。 + +**参数:** +- `category` - 日志分类 +- `message` - 日志消息内容 + +**返回:** 无 + +**复杂度:** O(n),n 为注册的 Sink 数量 + +**示例:** + +```cpp +#include + +XCEngine::Debug::Logger::Get().Fatal( + XCEngine::Debug::LogCategory::General, + "Out of memory - cannot continue" +); +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 diff --git a/docs/api/debug/logger/get.md b/docs/api/debug/logger/get.md new file mode 100644 index 0000000..19b348c --- /dev/null +++ b/docs/api/debug/logger/get.md @@ -0,0 +1,22 @@ +# Logger::Get + +```cpp +static Logger& Get() +``` + +获取 `Logger` 单例实例。Logger 使用局部静态变量实现 Meyers' Singleton,确保线程安全且只初始化一次。 + +**返回:** `Logger&` - 全局日志记录器实例的引用 + +**复杂度:** O(1) + +**示例:** + +```cpp +XCEngine::Debug::Logger& logger = XCEngine::Debug::Logger::Get(); +logger.Initialize(); +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 diff --git a/docs/api/debug/logger/info.md b/docs/api/debug/logger/info.md new file mode 100644 index 0000000..74292e6 --- /dev/null +++ b/docs/api/debug/logger/info.md @@ -0,0 +1,30 @@ +# Logger::Info + +```cpp +void Info(LogCategory category, const Containers::String& message) +``` + +记录一条 Info(2 级)日志。Info 级别用于一般性信息,如启动提示、配置加载等用户可见的正常运行消息。 + +**参数:** +- `category` - 日志分类 +- `message` - 日志消息内容 + +**返回:** 无 + +**复杂度:** O(n),n 为注册的 Sink 数量 + +**示例:** + +```cpp +#include + +XCEngine::Debug::Logger::Get().Info( + XCEngine::Debug::LogCategory::General, + "Application initialized successfully" +); +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 diff --git a/docs/api/debug/logger/initialize.md b/docs/api/debug/logger/initialize.md new file mode 100644 index 0000000..7841377 --- /dev/null +++ b/docs/api/debug/logger/initialize.md @@ -0,0 +1,28 @@ +# Logger::Initialize + +```cpp +void Initialize() +``` + +初始化日志系统。在首次使用日志功能前必须调用。初始化内部状态标志,确保日志系统已准备好工作。 + +**注意:** 默认最小日志级别为 `Verbose`,所有日志分类默认启用,这些是类成员变量的默认值,不需要在此方法中设置。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +int main() { + XCEngine::Debug::Logger::Get().Initialize(); + XCEngine::Debug::Logger::Get().AddSink(std::make_unique()); + XCEngine::Debug::Logger::Get().Info(XCEngine::Debug::LogCategory::General, "Application started"); + return 0; +} +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 diff --git a/docs/api/debug/logger/log.md b/docs/api/debug/logger/log.md new file mode 100644 index 0000000..8a74bae --- /dev/null +++ b/docs/api/debug/logger/log.md @@ -0,0 +1,45 @@ +# Logger::Log + +```cpp +void Log(LogLevel level, LogCategory category, + const Containers::String& message, const char* file = nullptr, + int32_t line = 0, const char* function = nullptr) +``` + +通用日志记录方法。根据设置的最小日志级别和分类开关决定是否输出,然后将日志分发给所有已注册的 Sink。如果日志级别低于最小级别或分类被禁用,则不输出。 + +**参数:** +- `level` - 日志级别(Verbose, Debug, Info, Warning, Error, Fatal) +- `category` - 日志分类(General, Rendering, Physics 等) +- `message` - 日志消息内容 +- `file` - 源代码文件路径(可选,默认 nullptr) +- `line` - 源代码行号(可选,默认 0) +- `function` - 函数名称(可选,默认 nullptr) + +**返回:** 无 + +**复杂度:** O(n),n 为注册的 Sink 数量 + +**示例:** + +```cpp +#include + +XCEngine::Debug::Logger::Get().Log( + XCEngine::Debug::LogLevel::Error, + XCEngine::Debug::LogCategory::FileSystem, + "Failed to open config file", + __FILE__, + __LINE__, + __FUNCTION__ +); + +// 推荐使用 XE_LOG 宏自动填充位置信息 +XE_LOG(XCEngine::Debug::LogCategory::General, XCEngine::Debug::LogLevel::Info, "Initialized"); +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 +- [LogLevel](../loglevel/loglevel.md) - 日志级别枚举 +- [LogCategory](../logcategory/logcategory.md) - 日志分类枚举 diff --git a/docs/api/debug/logger/logger.md b/docs/api/debug/logger/logger.md new file mode 100644 index 0000000..18c3e20 --- /dev/null +++ b/docs/api/debug/logger/logger.md @@ -0,0 +1,92 @@ +# Logger + +**命名空间**: `XCEngine::Debug` + +**类型**: `class` (singleton) + +**头文件**: `XCEngine/Debug/Logger.h` + +**描述**: 全局日志记录器单例,提供多级别、多分类的日志输出。 + +## 概述 + +`Logger` 是 XCEngine 的核心日志系统单例。它支持多个日志输出目标(Sink)、日志级别过滤、分类开关,并提供宏方便使用。 + +## 单例访问 + +| 方法 | 描述 | +|------|------| +| `static Logger& Get()` | 获取单例实例 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `void Initialize()` | [初始化日志系统](initialize.md) | +| `void Shutdown()` | [关闭日志系统](shutdown.md) | +| `void AddSink(std::unique_ptr sink)` | [添加日志输出目标](addsink.md) | +| `void RemoveSink(ILogSink* sink)` | [移除日志输出目标](removesink.md) | +| `void Log(...)` | [通用日志记录](log.md) | +| `void Verbose(...)` | [Verbose 级别日志](verbose.md) | +| `void Debug(...)` | [Debug 级别日志](debug.md) | +| `void Info(...)` | [Info 级别日志](info.md) | +| `void Warning(...)` | [Warning 级别日志](warning.md) | +| `void Error(...)` | [Error 级别日志](error.md) | +| `void Fatal(...)` | [Fatal 级别日志](fatal.md) | +| `void SetMinimumLevel(...)` | [设置最小日志级别](setminimumlevel.md) | +| `void SetCategoryEnabled(...)` | [开启/关闭指定分类](setcategoryenabled.md) | + +## 宏定义 + +### XE_LOG + +```cpp +#define XE_LOG(category, level, message) \ + XCEngine::Debug::Logger::Get().Log(level, category, message, __FILE__, __LINE__, __FUNCTION__) +``` + +通用日志宏,自动填充文件名、行号和函数名。 + +### XE_ASSERT + +```cpp +#define XE_ASSERT(condition, message) \ + if (!(condition)) { \ + XCEngine::Debug::Logger::Get().Fatal(XCEngine::Debug::LogCategory::General, message); \ + } +``` + +断言宏,条件失败时记录 Fatal 日志。 + +## 使用示例 + +```cpp +#include + +// 初始化 +Logger::Get().Initialize(); +Logger::Get().AddSink(std::make_unique()); +Logger::Get().AddSink(std::make_unique("app.log")); + +// 设置日志级别 +Logger::Get().SetMinimumLevel(LogLevel::Debug); + +// 使用便捷方法 +Logger::Get().Info(LogCategory::Rendering, "Render started"); +Logger::Get().Warning(LogCategory::Memory, "High memory usage"); +Logger::Get().Error(LogCategory::FileSystem, "Failed to load file"); + +// 使用宏(自动带位置信息) +XE_LOG(LogCategory::General, LogLevel::Info, "Application initialized"); + +// 使用断言 +XE_ASSERT(ptr != nullptr, "Pointer must not be null"); +``` + +## 相关文档 + +- [Debug 模块总览](../debug.md) - 返回模块总览 +- [ILogSink](../ilogsink/ilogsink.md) - 日志输出接口 +- [ConsoleLogSink](../consolelogsink/consolelogsink.md) - 控制台输出 +- [FileLogSink](../filelogsink/filelogsink.md) - 文件输出 +- [LogLevel](../loglevel/loglevel.md) - 日志级别枚举 diff --git a/docs/api/debug/logger/removesink.md b/docs/api/debug/logger/removesink.md new file mode 100644 index 0000000..bc81dab --- /dev/null +++ b/docs/api/debug/logger/removesink.md @@ -0,0 +1,29 @@ +# Logger::RemoveSink + +```cpp +void RemoveSink(ILogSink* sink) +``` + +从日志系统移除指定的输出目标。通过指针查找并移除对应的 Sink,Logger 不再向该目标发送日志。 + +**参数:** +- `sink` - 要移除的日志输出目标指针 + +**复杂度:** O(n),n 为注册的 Sink 数量 + +**示例:** + +```cpp +#include + +auto fileSink = std::make_unique("app.log"); +XCEngine::Debug::FileLogSink* rawPtr = fileSink.get(); +XCEngine::Debug::Logger::Get().AddSink(std::move(fileSink)); +// 稍后移除 +XCEngine::Debug::Logger::Get().RemoveSink(rawPtr); +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 +- [ILogSink](../ilogsink/ilogsink.md) - 日志输出接口 diff --git a/docs/api/debug/logger/setcategoryenabled.md b/docs/api/debug/logger/setcategoryenabled.md new file mode 100644 index 0000000..9f6b512 --- /dev/null +++ b/docs/api/debug/logger/setcategoryenabled.md @@ -0,0 +1,36 @@ +# Logger::SetCategoryEnabled + +```cpp +void SetCategoryEnabled(LogCategory category, bool enabled) +``` + +启用或禁用指定分类的日志输出。当分类被禁用时,该分类的所有日志都不会分发给 Sink,但级别过滤仍然适用。 + +**参数:** +- `category` - 要设置的日志分类 +- `enabled` - true 表示启用,false 表示禁用 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +// 禁用网络模块日志(减少日志噪音) +XCEngine::Debug::Logger::Get().SetCategoryEnabled( + XCEngine::Debug::LogCategory::Network, + false +); + +// 稍后重新启用 +XCEngine::Debug::Logger::Get().SetCategoryEnabled( + XCEngine::Debug::LogCategory::Network, + true +); +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 +- [LogCategory](../logcategory/logcategory.md) - 日志分类枚举 diff --git a/docs/api/debug/logger/setminimumlevel.md b/docs/api/debug/logger/setminimumlevel.md new file mode 100644 index 0000000..175fe78 --- /dev/null +++ b/docs/api/debug/logger/setminimumlevel.md @@ -0,0 +1,30 @@ +# Logger::SetMinimumLevel + +```cpp +void SetMinimumLevel(LogLevel level) +``` + +设置日志系统的最小输出级别。所有低于该级别的日志将被过滤,不会分发给任何 Sink。 + +**参数:** +- `level` - 最小日志级别 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +// 只输出 Warning 及以上级别的日志 +XCEngine::Debug::Logger::Get().SetMinimumLevel(XCEngine::Debug::LogLevel::Warning); + +// Verbose 和 Debug 级别的日志将被过滤 +XCEngine::Debug::Logger::Get().Verbose(XCEngine::Debug::LogCategory::General, "This will not be logged"); +XCEngine::Debug::Logger::Get().Warning(XCEngine::Debug::LogCategory::General, "This will be logged"); +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 +- [LogLevel](../loglevel/loglevel.md) - 日志级别枚举 diff --git a/docs/api/debug/logger/shutdown.md b/docs/api/debug/logger/shutdown.md new file mode 100644 index 0000000..79cc35b --- /dev/null +++ b/docs/api/debug/logger/shutdown.md @@ -0,0 +1,26 @@ +# Logger::Shutdown + +```cpp +void Shutdown() +``` + +关闭日志系统。移除所有注册的 Sink,刷新缓冲区并重置内部状态。在程序退出前调用,确保所有日志数据已写入输出目标。 + +**复杂度:** O(n),n 为注册的 Sink 数量 + +**示例:** + +```cpp +#include + +int main() { + XCEngine::Debug::Logger::Get().Initialize(); + // ... 应用逻辑 ... + XCEngine::Debug::Logger::Get().Shutdown(); + return 0; +} +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 diff --git a/docs/api/debug/logger/verbose.md b/docs/api/debug/logger/verbose.md new file mode 100644 index 0000000..9ef925b --- /dev/null +++ b/docs/api/debug/logger/verbose.md @@ -0,0 +1,30 @@ +# Logger::Verbose + +```cpp +void Verbose(LogCategory category, const Containers::String& message) +``` + +记录一条 Verbose(0 级)日志。Verbose 是最详细的日志级别,用于输出大量调试细节。 + +**参数:** +- `category` - 日志分类 +- `message` - 日志消息内容 + +**返回:** 无 + +**复杂度:** O(n),n 为注册的 Sink 数量 + +**示例:** + +```cpp +#include + +XCEngine::Debug::Logger::Get().Verbose( + XCEngine::Debug::LogCategory::Memory, + "Memory pool fragmentation: 12.5%" +); +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 diff --git a/docs/api/debug/logger/warning.md b/docs/api/debug/logger/warning.md new file mode 100644 index 0000000..f7e7efc --- /dev/null +++ b/docs/api/debug/logger/warning.md @@ -0,0 +1,30 @@ +# Logger::Warning + +```cpp +void Warning(LogCategory category, const Containers::String& message) +``` + +记录一条 Warning(3 级)日志。Warning 级别用于指示潜在问题但程序仍可继续运行的情况,如资源即将耗尽、配置值超出建议范围等。 + +**参数:** +- `category` - 日志分类 +- `message` - 日志消息内容 + +**返回:** 无 + +**复杂度:** O(n),n 为注册的 Sink 数量 + +**示例:** + +```cpp +#include + +XCEngine::Debug::Logger::Get().Warning( + XCEngine::Debug::LogCategory::Memory, + "Memory usage exceeds 80% of available heap" +); +``` + +## 相关文档 + +- [Logger 总览](logger.md) - 返回类总览 diff --git a/docs/api/debug/loglevel/loglevel.md b/docs/api/debug/loglevel/loglevel.md new file mode 100644 index 0000000..eda973b --- /dev/null +++ b/docs/api/debug/loglevel/loglevel.md @@ -0,0 +1,40 @@ +# LogLevel + +**命名空间**: `XCEngine::Debug` + +**类型**: `enum class` + +**描述**: 日志级别枚举,定义日志的严重程度。 + +## 概述 + +`LogLevel` 枚举定义了从最详细到最严重的日志级别。`Logger` 根据设置的最小级别过滤日志。 + +## 枚举值 + +| 值 | 说明 | 数值 | +|----|------|------| +| `Verbose` | 详细调试信息 | 0 | +| `Debug` | 调试信息 | 1 | +| `Info` | 一般信息 | 2 | +| `Warning` | 警告信息 | 3 | +| `Error` | 错误信息 | 4 | +| `Fatal` | 致命错误 | 5 | + +## 辅助函数 + +| 函数 | 描述 | +|------|------| +| `const char* LogLevelToString(LogLevel level)` | [将日志级别转换为字符串](logleveltostring.md) | + +## 使用示例 + +```cpp +Logger::Get().SetMinimumLevel(LogLevel::Warning); +// 只有 Warning、Error、Fatal 级别的日志会被输出 +``` + +## 相关文档 + +- [Debug 模块总览](../debug.md) - 返回模块总览 +- [Logger](../logger/logger.md) - 日志记录器 diff --git a/docs/api/debug/loglevel/logleveltostring.md b/docs/api/debug/loglevel/logleveltostring.md new file mode 100644 index 0000000..b07e98d --- /dev/null +++ b/docs/api/debug/loglevel/logleveltostring.md @@ -0,0 +1,28 @@ +# LogLevelToString + +```cpp +const char* LogLevelToString(LogLevel level) +``` + +将 `LogLevel` 枚举值转换为可读字符串。 + +**参数:** +- `level` - 日志级别 + +**返回:** 对应级别的字符串("VERBOSE", "DEBUG", "INFO", "WARNING", "ERROR", "FATAL") + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +XCEngine::Debug::LogLevel level = XCEngine::Debug::LogLevel::Error; +const char* str = XCEngine::Debug::LogLevelToString(level); +// str == "ERROR" +``` + +## 相关文档 + +- [LogLevel 总览](loglevel.md) - 返回类总览 diff --git a/docs/api/debug/profiler/beginframe.md b/docs/api/debug/profiler/beginframe.md new file mode 100644 index 0000000..109142d --- /dev/null +++ b/docs/api/debug/profiler/beginframe.md @@ -0,0 +1,26 @@ +# Profiler::BeginFrame + +```cpp +void BeginFrame() +``` + +开始一帧的性能分析。记录当前帧的起始时间戳,用于计算帧级别的性能指标。应在每帧渲染开始时调用。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +void GameLoop() { + XCEngine::Debug::Profiler::Get().BeginFrame(); + Update(); + Render(); + XCEngine::Debug::Profiler::Get().EndFrame(); +} +``` + +## 相关文档 + +- [Profiler 总览](profiler.md) - 返回类总览 diff --git a/docs/api/debug/profiler/beginprofile.md b/docs/api/debug/profiler/beginprofile.md new file mode 100644 index 0000000..0203a51 --- /dev/null +++ b/docs/api/debug/profiler/beginprofile.md @@ -0,0 +1,36 @@ +# Profiler::BeginProfile + +```cpp +void BeginProfile(const char* name) +``` + +开始一个性能分析块。将分析节点压入栈中并记录开始时间。每次调用 `BeginProfile` 应与一次 `EndProfile` 配对使用。 + +**参数:** +- `name` - 分析块的名称,用于在导出结果中标识 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +void ProcessMesh() { + XCEngine::Debug::Profiler::Get().BeginProfile("ProcessMesh"); + + XCEngine::Debug::Profiler::Get().BeginProfile("ComputeVertices"); + ComputeVertices(); + XCEngine::Debug::Profiler::Get().EndProfile(); + + XCEngine::Debug::Profiler::Get().BeginProfile("ComputeIndices"); + ComputeIndices(); + XCEngine::Debug::Profiler::Get().EndProfile(); + + XCEngine::Debug::Profiler::Get().EndProfile(); +} +``` + +## 相关文档 + +- [Profiler 总览](profiler.md) - 返回类总览 diff --git a/docs/api/debug/profiler/endframe.md b/docs/api/debug/profiler/endframe.md new file mode 100644 index 0000000..d9e208b --- /dev/null +++ b/docs/api/debug/profiler/endframe.md @@ -0,0 +1,26 @@ +# Profiler::EndFrame + +```cpp +void EndFrame() +``` + +结束一帧的性能分析。记录当前帧的结束时间,计算帧耗时并可用于帧率统计。应在每帧渲染结束时调用。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +void GameLoop() { + XCEngine::Debug::Profiler::Get().BeginFrame(); + Update(); + Render(); + XCEngine::Debug::Profiler::Get().EndFrame(); +} +``` + +## 相关文档 + +- [Profiler 总览](profiler.md) - 返回类总览 diff --git a/docs/api/debug/profiler/endprofile.md b/docs/api/debug/profiler/endprofile.md new file mode 100644 index 0000000..c231a29 --- /dev/null +++ b/docs/api/debug/profiler/endprofile.md @@ -0,0 +1,25 @@ +# Profiler::EndProfile + +```cpp +void EndProfile() +``` + +结束当前性能分析块。从栈顶弹出分析节点并计算持续时间(endTime - startTime),将结果保存到样本列表中。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +void RenderPipeline() { + XCEngine::Debug::Profiler::Get().BeginProfile("RenderPipeline"); + // ... 渲染逻辑 ... + XCEngine::Debug::Profiler::Get().EndProfile(); +} +``` + +## 相关文档 + +- [Profiler 总览](profiler.md) - 返回类总览 diff --git a/docs/api/debug/profiler/exportchrometracing.md b/docs/api/debug/profiler/exportchrometracing.md new file mode 100644 index 0000000..f0f7829 --- /dev/null +++ b/docs/api/debug/profiler/exportchrometracing.md @@ -0,0 +1,45 @@ +# Profiler::ExportChromeTracing + +```cpp +void ExportChromeTracing(const Containers::String& filePath) +``` + +**状态:** 此方法目前为空实现,暂未功能。 + +将收集的性能数据导出为 Chrome Tracing JSON 格式。导出的文件可通过 Chrome 浏览器打开(地址栏输入 `chrome://tracing` 并加载文件)进行可视化分析。 + +**参数:** +- `filePath` - 输出文件路径 + +**复杂度:** O(n),n 为记录的样本数量 + +**示例:** + +```cpp +#include + +XCEngine::Debug::Profiler::Get().Initialize(); + +void RenderFrame() { + XCEngine::Debug::Profiler::Get().BeginFrame(); + XE_PROFILE_FUNCTION(); + + XE_PROFILE_BEGIN("UpdateScene"); + UpdateScene(); + XE_PROFILE_END(); + + XE_PROFILE_BEGIN("DrawScene"); + DrawScene(); + XE_PROFILE_END(); + + XCEngine::Debug::Profiler::Get().EndFrame(); +} + +// 运行一段时间后导出 +XCEngine::Debug::Profiler::Get().ExportChromeTracing("trace.json"); +XCEngine::Debug::Profiler::Get().Shutdown(); +``` + +## 相关文档 + +- [Profiler 总览](profiler.md) - 返回类总览 diff --git a/docs/api/debug/profiler/get.md b/docs/api/debug/profiler/get.md new file mode 100644 index 0000000..7ee09d6 --- /dev/null +++ b/docs/api/debug/profiler/get.md @@ -0,0 +1,22 @@ +# Profiler::Get + +```cpp +static Profiler& Get() +``` + +获取 `Profiler` 单例实例。Profiler 使用局部静态变量实现 Meyers' Singleton,确保线程安全且只初始化一次。 + +**返回:** `Profiler&` - 全局性能分析器实例的引用 + +**复杂度:** O(1) + +**示例:** + +```cpp +XCEngine::Debug::Profiler& profiler = XCEngine::Debug::Profiler::Get(); +profiler.Initialize(); +``` + +## 相关文档 + +- [Profiler 总览](profiler.md) - 返回类总览 diff --git a/docs/api/debug/profiler/initialize.md b/docs/api/debug/profiler/initialize.md new file mode 100644 index 0000000..eb9dcef --- /dev/null +++ b/docs/api/debug/profiler/initialize.md @@ -0,0 +1,30 @@ +# Profiler::Initialize + +```cpp +void Initialize() +``` + +初始化性能分析器。在首次使用性能分析功能前必须调用。初始化内部状态标志,确保分析器已准备好工作。 + +**注意:** 帧计时器等数据结构在首次 BeginFrame 时自动初始化。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +int main() { + XCEngine::Debug::Profiler::Get().Initialize(); + XCEngine::Debug::Profiler::Get().BeginFrame(); + // ... 性能测量 ... + XCEngine::Debug::Profiler::Get().EndFrame(); + XCEngine::Debug::Profiler::Get().Shutdown(); + return 0; +} +``` + +## 相关文档 + +- [Profiler 总览](profiler.md) - 返回类总览 diff --git a/docs/api/debug/profiler/markevent.md b/docs/api/debug/profiler/markevent.md new file mode 100644 index 0000000..b1c7325 --- /dev/null +++ b/docs/api/debug/profiler/markevent.md @@ -0,0 +1,36 @@ +# Profiler::MarkEvent + +```cpp +void MarkEvent(const char* name, uint64_t timestamp, uint32_t threadId) +``` + +**状态:** 此方法目前为空实现,暂未功能。 + +在指定时间点标记一个事件。用于记录离散的瞬时事件,如 GPU 命令提交、状态切换等,通常用于多线程性能分析。 + +**参数:** +- `name` - 事件名称 +- `timestamp` - 事件发生的时间戳(微秒) +- `threadId` - 事件所属的线程 ID + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +// 在多线程场景中标记事件 +void WorkerThread() { + uint32_t tid = GetCurrentThreadId(); + uint64_t ts = GetTickCount(); + + XCEngine::Debug::Profiler::Get().MarkEvent("TaskStarted", ts, tid); + DoWork(); + XCEngine::Debug::Profiler::Get().MarkEvent("TaskCompleted", GetTickCount(), tid); +} +``` + +## 相关文档 + +- [Profiler 总览](profiler.md) - 返回类总览 diff --git a/docs/api/debug/profiler/profiler.md b/docs/api/debug/profiler/profiler.md new file mode 100644 index 0000000..23d7eaf --- /dev/null +++ b/docs/api/debug/profiler/profiler.md @@ -0,0 +1,136 @@ +# Profiler + +**命名空间**: `XCEngine::Debug` + +**类型**: `class` (singleton) + +**描述**: 性能分析器单例,用于测量代码块执行时间并支持 Chrome Tracing 格式导出。 + +## 概述 + +`Profiler` 是 XCEngine 的性能分析工具。它通过栈式记录和采样方式跟踪函数执行时间,支持导出为 Chrome Tracing 格式(可通过 Chrome 的 `chrome://tracing` 查看)。 + +## 单例访问 + +| 方法 | 描述 | +|------|------| +| `static Profiler& Get()` | 获取单例实例 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `void Initialize()` | [初始化性能分析器](initialize.md) | +| `void Shutdown()` | [关闭性能分析器](shutdown.md) | +| `void BeginProfile(const char* name)` | [开始一个性能分析块](beginprofile.md) | +| `void EndProfile()` | [结束当前性能分析块](endprofile.md) | +| `void BeginFrame()` | [开始一帧的分析](beginframe.md) | +| `void EndFrame()` | [结束一帧的分析](endframe.md) | +| `void MarkEvent(const char* name, uint64_t timestamp, uint32_t threadId)` | [标记一个事件点](markevent.md) | +| `void SetMarker(const char* name, uint32_t color)` | [设置帧标记](setmarker.md) | +| `void ExportChromeTracing(const Containers::String& filePath)` | [导出为 Chrome Tracing JSON 格式](exportchrometracing.md) | + +## 宏定义 + +### XE_PROFILE_BEGIN + +```cpp +#define XE_PROFILE_BEGIN(name) XCEngine::Debug::Profiler::Get().BeginProfile(name) +``` + +开始分析指定名称的代码块。 + +### XE_PROFILE_END + +```cpp +#define XE_PROFILE_END() XCEngine::Debug::Profiler::Get().EndProfile() +``` + +结束当前分析块。 + +### XE_PROFILE_FUNCTION + +```cpp +#define XE_PROFILE_FUNCTION() XE_PROFILE_BEGIN(__FUNCTION__) +``` + +自动使用当前函数名进行分析。 + +## 私有成员 + +### ProfileNode + +```cpp +struct ProfileNode { + const char* name; + uint64_t startTime; + uint64_t endTime; + uint32_t threadId; +}; +``` + +内部使用的性能分析节点结构,用于在栈上跟踪嵌套的分析块。 + +### ProfileSample + +```cpp +struct ProfileSample { + const char* name; + uint64_t duration; + uint32_t threadId; +}; +``` + +记录单个性能样本的结构,包含名称、持续时间和线程 ID。 + +## 成员变量 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `m_profileStack` | `std::vector` | 分析块栈,用于跟踪嵌套调用 | +| `m_samples` | `std::vector` | 样本列表,记录完成的性能数据 | +| `m_frameStartTime` | `uint64_t` | 当前帧开始时间戳(微秒) | +| `m_initialized` | `bool` | 初始化标志 | + +## 实现状态 + +以下方法目前为存根(stub)实现,尚未完成功能: + +| 方法 | 状态 | +|------|------| +| `void MarkEvent(const char* name, uint64_t timestamp, uint32_t threadId)` | 存根 | +| `void SetMarker(const char* name, uint32_t color)` | 存根 | +| `void ExportChromeTracing(const Containers::String& filePath)` | 存根 | + +## 使用示例 + +```cpp +Profiler::Get().Initialize(); + +void RenderFrame() { + XE_PROFILE_FUNCTION(); + + { + XE_PROFILE_BEGIN("UpdateGeometry"); + UpdateGeometry(); + XE_PROFILE_END(); + } + + { + XE_PROFILE_BEGIN("DrawCalls"); + DrawCalls(); + XE_PROFILE_END(); + } +} + +Profiler::Get().BeginFrame(); +// ... 渲染帧 ... +Profiler::Get().EndFrame(); +Profiler::Get().ExportChromeTracing("profile.json"); +Profiler::Get().Shutdown(); +``` + +## 相关文档 + +- [Debug 模块总览](../debug.md) - 返回模块总览 +- [Logger](../logger/logger.md) - 日志记录器 diff --git a/docs/api/debug/profiler/setmarker.md b/docs/api/debug/profiler/setmarker.md new file mode 100644 index 0000000..a9610c8 --- /dev/null +++ b/docs/api/debug/profiler/setmarker.md @@ -0,0 +1,33 @@ +# Profiler::SetMarker + +```cpp +void SetMarker(const char* name, uint32_t color) +``` + +**状态:** 此方法目前为空实现,暂未功能。 + +在 Chrome Tracing 时间线上设置一个标记点,用于标记特定位置或状态。标记会显示为一条垂直线,便于在性能图中定位关键事件。 + +**参数:** +- `name` - 标记名称 +- `color` - 标记颜色(ABGR 格式) + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +void OnVBlank() { + XCEngine::Debug::Profiler::Get().SetMarker("VBlank", 0xFF00FF00); // 绿色 +} + +void OnRenderComplete() { + XCEngine::Debug::Profiler::Get().SetMarker("FrameRendered", 0xFFFF0000); // 红色 +} +``` + +## 相关文档 + +- [Profiler 总览](profiler.md) - 返回类总览 diff --git a/docs/api/debug/profiler/shutdown.md b/docs/api/debug/profiler/shutdown.md new file mode 100644 index 0000000..8d01e54 --- /dev/null +++ b/docs/api/debug/profiler/shutdown.md @@ -0,0 +1,22 @@ +# Profiler::Shutdown + +```cpp +void Shutdown() +``` + +关闭性能分析器。清理内部数据结构,停止所有活动分析块,重置状态。在程序退出前调用。 + +**复杂度:** O(1) + +**示例:** + +```cpp +XCEngine::Debug::Profiler::Get().Initialize(); +// ... 使用 Profiler ... +XCEngine::Debug::Profiler::Get().ExportChromeTracing("profile.json"); +XCEngine::Debug::Profiler::Get().Shutdown(); +``` + +## 相关文档 + +- [Profiler 总览](profiler.md) - 返回类总览 diff --git a/docs/api/fix_links.py b/docs/api/fix_links.py new file mode 100644 index 0000000..36867ea --- /dev/null +++ b/docs/api/fix_links.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python3 +""" +Fix broken cross-references in API documentation. +""" + +import os +import re +from pathlib import Path + +API_DOCS_ROOT = Path(r"D:\Xuanchi\Main\XCEngine\docs\api") + + +def normalize_path(path_str): + """Remove duplicate path segments like ./module/./module/.""" + parts = [] + for part in path_str.replace("\\", "/").split("/"): + if part == "." or part == "": + continue + parts.append(part) + return "/".join(parts) + + +def resolve_reference(current_file, ref_path): + """Resolve a reference path relative to current file and check if it exists.""" + current_file = Path(current_file) + parent_dir = current_file.parent + + # Normalize the reference path + normalized_ref = normalize_path(ref_path) + + # Try to resolve the path + resolved = (parent_dir / normalized_ref).resolve() + + # Also try with normalized path + resolved2 = (parent_dir / ref_path.replace("\\", "/")).resolve() + + return resolved, resolved2 + + +def get_relative_path(from_file, to_file): + """Get correct relative path from one file to another.""" + from_file = Path(from_file) + to_file = Path(to_file) + + # Get common prefix + from_parts = from_file.parts + to_parts = to_file.parts + + # Find common prefix length + common_len = 0 + for i in range(min(len(from_parts), len(to_parts))): + if from_parts[i] == to_parts[i]: + common_len = i + 1 + else: + break + + # Build relative path + up_count = len(from_parts) - common_len - 1 # -1 for the filename + parts = [".."] * up_count + list(to_parts[common_len:]) + + return "/".join(parts) + + +def find_file_by_name(target_name, base_dir): + """Find a file with given name in the base directory.""" + base_dir = Path(base_dir) + api_docs = API_DOCS_ROOT + + # Search for the file + pattern = f"**/{target_name}" + matches = list(api_docs.glob(pattern)) + + # Filter for exact filename match + for match in matches: + if match.name == target_name: + return match + + return None + + +def fix_links_in_file(file_path, verbose=True): + """Analyze and fix links in a single file.""" + file_path = Path(file_path) + + if not file_path.exists(): + return [] + + with open(file_path, "r", encoding="utf-8") as f: + content = f.read() + + original_content = content + fixes = [] + + # Find all markdown links: [text](path) + link_pattern = r"\[([^\]]*)\]\(([^)]+\.md)\)" + + def replace_link(match): + link_text = match.group(1) + link_path = match.group(2) + + # Skip external links + if link_path.startswith("http://") or link_path.startswith("https://"): + return match.group(0) + + # Skip anchor links + if link_path.startswith("#"): + return match.group(0) + + # Normalize the path + normalized = normalize_path(link_path) + + # Try to resolve the target file + parent_dir = file_path.parent + + # Try the exact path first + target_path = parent_dir / link_path.replace("\\", "/") + target_exists = target_path.exists() + + if not target_exists: + # Try normalized path + target_path = parent_dir / normalized + target_exists = target_path.exists() + + if not target_exists: + # Try to find the file elsewhere + # Get just the filename + filename = Path(normalized).name + + # Try to find it + found = find_file_by_name(filename, API_DOCS_ROOT) + if found: + # Calculate correct relative path + correct_rel = get_relative_path(file_path, found) + if correct_rel != normalized: + fixes.append( + { + "file": file_path, + "line": content[: match.start()].count("\n") + 1, + "old": link_path, + "new": correct_rel, + "target": found, + } + ) + return f"[{link_text}]({correct_rel})" + else: + fixes.append( + { + "file": file_path, + "line": content[: match.start()].count("\n") + 1, + "old": link_path, + "new": None, + "target": None, + "error": "Target file not found", + } + ) + return match.group(0) + elif normalized != link_path: + # Path has duplicate segments that need fixing + fixes.append( + { + "file": file_path, + "line": content[: match.start()].count("\n") + 1, + "old": link_path, + "new": normalized, + "target": target_path, + } + ) + return f"[{link_text}]({normalized})" + + return match.group(0) + + new_content = re.sub(link_pattern, replace_link, content) + + if new_content != original_content: + with open(file_path, "w", encoding="utf-8") as f: + f.write(new_content) + + return fixes + + +def main(): + print("=" * 70) + print("API Documentation Cross-Reference Fixer") + print("=" * 70) + + # Collect all markdown files + md_files = list(API_DOCS_ROOT.glob("**/*.md")) + print(f"\nFound {len(md_files)} markdown files in {API_DOCS_ROOT}") + + all_fixes = [] + broken_refs = [] + + for md_file in md_files: + fixes = fix_links_in_file(md_file, verbose=False) + for fix in fixes: + if fix.get("error"): + broken_refs.append(fix) + else: + all_fixes.append(fix) + + print(f"\n{'=' * 70}") + print("FIXES APPLIED:") + print("=" * 70) + + if all_fixes: + for fix in all_fixes: + rel_file = fix["file"].relative_to(API_DOCS_ROOT) + print(f"\n File: {rel_file}") + print(f" Line: {fix['line']}") + print(f" Old: {fix['old']}") + print(f" New: {fix['new']}") + else: + print("\n No fixes needed.") + + print(f"\n{'=' * 70}") + print("BROKEN REFERENCES (target files don't exist):") + print("=" * 70) + + if broken_refs: + for ref in broken_refs: + rel_file = ref["file"].relative_to(API_DOCS_ROOT) + print(f"\n File: {rel_file}") + print(f" Line: {ref['line']}") + print(f" Broken ref: {ref['old']}") + else: + print("\n No broken references found.") + + print(f"\n{'=' * 70}") + print(f"SUMMARY:") + print(f" Total fixes applied: {len(all_fixes)}") + print(f" Broken references: {len(broken_refs)}") + print("=" * 70) + + return len(all_fixes), len(broken_refs) + + +if __name__ == "__main__": + main() diff --git a/docs/api/main.md b/docs/api/main.md new file mode 100644 index 0000000..1f9f256 --- /dev/null +++ b/docs/api/main.md @@ -0,0 +1,94 @@ +# XCEngine API 文档总索引 + +**描述**: XCEngine 图形引擎的完整 API 文档索引。 + +--- + +## 模块导航 + +| 模块 | 文档目录 | 描述 | +|------|----------|------| +| **RHI** | [rhi/](rhi/rhi.md) | 渲染硬件接口抽象层 | +| **D3D12** | [rhi/d3d12/](rhi/opengl/overview.md) | DirectX 12 后端实现 | +| **OpenGL** | [rhi/opengl/](rhi/opengl/overview.md) | OpenGL 后端实现 | +| **Containers** | [containers/](containers/containers.md) | 容器数据结构 | +| **Memory** | [memory/](memory/memory.md) | 内存管理 | +| **Threading** | [threading/](threading/threading.md) | 多线程和任务系统 | +| **Core** | [core/](core/core.md) | 核心基础类型 | +| **Debug** | [debug/](debug/debug.md) | 调试和日志 | +| **Math** | [math/](math/math.md) | 数学库 | +| **Resources** | [resources/](resources/resources.md) | 资源管理系统 | + +--- + +## 快速开始 + +### 创建渲染设备 + +```cpp +#include +#include + +// 创建 D3D12 设备 +RHI::RHIDevice* device = RHI::RHIFactory::CreateRHIDevice(RHI::RHIType::D3D12); + +// 初始化 +RHI::RHIDeviceDesc desc; +desc.windowHandle = hwnd; +device->Initialize(desc); +``` + +### 使用资源管理器 + +```cpp +#include + +// 加载纹理 +auto texture = Resources::ResourceManager::Get().Load("textures/player.png"); + +// 加载网格 +auto mesh = Resources::ResourceManager::Get().Load("models/player.fbx"); +``` + +### 日志记录 + +```cpp +#include + +// 记录日志 +XE_LOG(Debug::LogCategory::Rendering, Debug::LogLevel::Info, "Render started"); +``` + +### 数学运算 + +```cpp +#include + +// 创建变换矩阵 +Math::Matrix4 transform = Math::Matrix4::TRS(position, rotation, scale); +``` + +--- + +## 文档统计 + +| 模块 | 文档数量 | +|------|----------| +| RHI 抽象层 | 17 | +| D3D12 后端 | 24 | +| OpenGL 后端 | 14 | +| Math | 17 | +| Resources | 17 | +| Threading | 10 | +| Memory | 6 | +| Debug | 9 | +| Core | 6 | +| Containers | 4 | +| **总计** | **124** | + +--- + +## 相关文档 + +- [XCEngine 架构设计](../../docs/plan/XCEngine渲染引擎架构设计.md) +- [RHI 抽象层设计](../../docs/plan/RHI抽象层设计与实现.md) diff --git a/docs/api/math/aabb/aabb.md b/docs/api/math/aabb/aabb.md new file mode 100644 index 0000000..637ef6c --- /dev/null +++ b/docs/api/math/aabb/aabb.md @@ -0,0 +1,43 @@ +# AABB / OBB + +轴对齐包围盒 (AABB) 和有向包围盒 (OBB)。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## AABB + +`AABB` 在 Math 库中通过 `Bounds` 类型实现,参见 [./bounds/bounds.md](../bounds/bounds.md)。 + +## OBB - 有向包围盒 + +OBB 是可以任意方向旋转的包围盒。 + +```cpp +struct OBB { + Vector3 center; + Vector3 extents; + Matrix4 transform; +}; +``` + +### 构造函数 + +- `OBB()` - 默认构造 +- `OBB(const Vector3& center, const Vector3& extents)` - 从中心和半长构造 + +### 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [GetAxis(index)](getaxis.md) | `Vector3` | 获取局部轴(index 必须是 0、1 或 2) | +| [GetMin()](../box/getmin.md) | `Vector3` | 局部空间最小点 | +| [GetMax()](../box/getmax.md) | `Vector3` | 局部空间最大点 | +| [Contains(point)](../box/contains.md) | `bool` | 点是否在 OBB 内 | +| [Intersects(OBB)](intersects-obb.md) | `bool` | 与另一个 OBB 相交 | +| [Intersects(Sphere)](intersects-sphere.md) | `bool` | 与球体相交 | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/aabb/getaxis.md b/docs/api/math/aabb/getaxis.md new file mode 100644 index 0000000..769e6ec --- /dev/null +++ b/docs/api/math/aabb/getaxis.md @@ -0,0 +1,23 @@ +# OBB::GetAxis + +```cpp +Vector3 GetAxis(int index) const +``` + +获取 OBB 的局部坐标轴。 + +**参数:** +- `index` - 轴索引(0=X轴, 1=Y轴, 2=Z轴) + +**返回:** `Vector3` - 对应轴的方向向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +OBB obb = ...; +Vector3 xAxis = obb.GetAxis(0); // 局部 X 轴 +Vector3 yAxis = obb.GetAxis(1); // 局部 Y 轴 +Vector3 zAxis = obb.GetAxis(2); // 局部 Z 轴 +``` diff --git a/docs/api/math/aabb/intersects-obb.md b/docs/api/math/aabb/intersects-obb.md new file mode 100644 index 0000000..feeadb9 --- /dev/null +++ b/docs/api/math/aabb/intersects-obb.md @@ -0,0 +1,24 @@ +# OBB::Intersects (OBB) + +```cpp +bool Intersects(const OBB& other) const +``` + +检测两个 OBB 是否相交(使用 SAT 分离轴定理)。 + +**参数:** +- `other` - 另一个 OBB + +**返回:** `bool` - true 表示相交 + +**复杂度:** O(1) + +**示例:** + +```cpp +OBB obbA = ...; +OBB obbB = ...; +if (obbA.Intersects(obbB)) { + // 两个有向包围盒相交 +} +``` diff --git a/docs/api/math/aabb/intersects-sphere.md b/docs/api/math/aabb/intersects-sphere.md new file mode 100644 index 0000000..13d919a --- /dev/null +++ b/docs/api/math/aabb/intersects-sphere.md @@ -0,0 +1,24 @@ +# OBB::Intersects (Sphere) + +```cpp +bool Intersects(const Sphere& sphere) const +``` + +检测 OBB 是否与球体相交。 + +**参数:** +- `sphere` - 要检测的球体 + +**返回:** `bool` - true 表示相交 + +**复杂度:** O(1) + +**示例:** + +```cpp +OBB obb = ...; +Sphere sphere = ...; +if (obb.Intersects(sphere)) { + // OBB 与球体相交 +} +``` diff --git a/docs/api/math/aabb/obb-contains.md b/docs/api/math/aabb/obb-contains.md new file mode 100644 index 0000000..9aee18e --- /dev/null +++ b/docs/api/math/aabb/obb-contains.md @@ -0,0 +1,20 @@ +# OBB::Contains + +```cpp +bool Contains(const Vector3& point) const +``` + +检测点是否在 OBB 内。 + +**参数:** +- `point` - 要检测的点 + +**返回:** `bool` - true 表示点在 OBB 内 + +**复杂度:** O(1) + +**示例:** + +```cpp +if (obb.Contains(point)) { /* inside */ } +``` diff --git a/docs/api/math/aabb/obb-getaxis.md b/docs/api/math/aabb/obb-getaxis.md new file mode 100644 index 0000000..c438abc --- /dev/null +++ b/docs/api/math/aabb/obb-getaxis.md @@ -0,0 +1,20 @@ +# OBB::GetAxis + +```cpp +Vector3 GetAxis(int index) const +``` + +获取 OBB 的局部轴。 + +**参数:** +- `index` - 轴索引 (0=X, 1=Y, 2=Z) + +**返回:** `Vector3` - 对应的局部轴 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 xAxis = obb.GetAxis(0); +``` diff --git a/docs/api/math/aabb/obb-getmax.md b/docs/api/math/aabb/obb-getmax.md new file mode 100644 index 0000000..04e56e8 --- /dev/null +++ b/docs/api/math/aabb/obb-getmax.md @@ -0,0 +1,17 @@ +# OBB::GetMax + +```cpp +Vector3 GetMax() const +``` + +获取局部空间最大点。 + +**返回:** `Vector3` - center + extents + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 max = obb.GetMax(); +``` diff --git a/docs/api/math/aabb/obb-getmin.md b/docs/api/math/aabb/obb-getmin.md new file mode 100644 index 0000000..34d1bf1 --- /dev/null +++ b/docs/api/math/aabb/obb-getmin.md @@ -0,0 +1,17 @@ +# OBB::GetMin + +```cpp +Vector3 GetMin() const +``` + +获取局部空间最小点。 + +**返回:** `Vector3` - center - extents + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 min = obb.GetMin(); +``` diff --git a/docs/api/math/aabb/obb-intersects-obb.md b/docs/api/math/aabb/obb-intersects-obb.md new file mode 100644 index 0000000..fb06b8a --- /dev/null +++ b/docs/api/math/aabb/obb-intersects-obb.md @@ -0,0 +1,25 @@ +# OBB::Intersects(OBB) + +```cpp +bool Intersects(const OBB& other) const; +``` + +判断两个 OBB 是否相交(SAT 分离轴定理)。 + +**返回:** 两包围盒是否相交 + +**复杂度:** O(1) + +**示例:** + +```cpp +OBB a(centerA, extentsA); +OBB b(centerB, extentsB); +if (a.Intersects(b)) { + // 两包围盒相交 +} +``` + +## 相关文档 + +- [AABB 总览](aabb.md) - 返回 AABB 概览 diff --git a/docs/api/math/aabb/obb-intersects-sphere.md b/docs/api/math/aabb/obb-intersects-sphere.md new file mode 100644 index 0000000..57071ef --- /dev/null +++ b/docs/api/math/aabb/obb-intersects-sphere.md @@ -0,0 +1,28 @@ +# OBB::Intersects(Sphere) + +```cpp +bool Intersects(const Sphere& sphere) const; +``` + +判断 OBB 与球体是否相交。 + +**参数:** +- `sphere` - 球体 + +**返回:** OBB 与球体是否相交 + +**复杂度:** O(1) + +**示例:** + +```cpp +OBB obb(center, extents); +Sphere s(sphereCenter, radius); +if (obb.Intersects(s)) { + // OBB 与球体相交 +} +``` + +## 相关文档 + +- [AABB 总览](aabb.md) - 返回 AABB 概览 diff --git a/docs/api/math/bounds/bounds.md b/docs/api/math/bounds/bounds.md new file mode 100644 index 0000000..ba8aaf2 --- /dev/null +++ b/docs/api/math/bounds/bounds.md @@ -0,0 +1,40 @@ +# Bounds + +轴对齐包围盒 (AABB),中心-范围表示。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 结构体定义 + +```cpp +struct Bounds { + Vector3 center = Vector3::Zero(); + Vector3 extents = Vector3::Zero(); +}; +``` + +## 构造函数 + +- `Bounds()` - 默认构造 +- `Bounds(const Vector3& center, const Vector3& size)` - 从中心和大小构造 + +## 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [GetMin()](getmin.md) | `Vector3` | 最小点 | +| [GetMax()](getmax.md) | 最大点 | +| [SetMinMax(min, max)](setminmax.md) | `void` | 从最小/最大点设置 | +| [Contains(point)](contains.md) | `bool` | 点是否在盒内 | +| [Intersects(other)](intersects.md) | `bool` | 与另一个 Bounds 相交 | +| [Encapsulate(point)](encapsulate.md) | `void` | 扩展包含点 | +| [Encapsulate(bounds)](encapsulate-bounds.md) | `void` | 扩展包含另一个 Bounds | +| [Expand(amount)](expand.md) | `void` | 扩展包围盒 | +| [GetClosestPoint(point)](getclosestpoint.md) | `Vector3` | 盒上最接近的点 | +| [GetVolume()](getvolume.md) | `float` | 体积 | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/bounds/contains.md b/docs/api/math/bounds/contains.md new file mode 100644 index 0000000..12cb6ef --- /dev/null +++ b/docs/api/math/bounds/contains.md @@ -0,0 +1,20 @@ +# Bounds::Contains + +```cpp +bool Contains(const Vector3& point) const +``` + +检测点是否在包围盒内。 + +**参数:** +- `point` - 要检测的点 + +**返回:** `bool` - true 表示点在盒内 + +**复杂度:** O(1) + +**示例:** + +```cpp +if (bounds.Contains(point)) { /* inside */ } +``` diff --git a/docs/api/math/bounds/encapsulate-bounds.md b/docs/api/math/bounds/encapsulate-bounds.md new file mode 100644 index 0000000..b628610 --- /dev/null +++ b/docs/api/math/bounds/encapsulate-bounds.md @@ -0,0 +1,18 @@ +# Bounds::Encapsulate (Bounds) + +```cpp +void Encapsulate(const Bounds& bounds) +``` + +扩展包围盒以包含另一个 Bounds。 + +**参数:** +- `bounds` - 要包含的 Bounds + +**复杂度:** O(1) + +**示例:** + +```cpp +bounds.Encapsulate(otherBounds); +``` diff --git a/docs/api/math/bounds/encapsulate.md b/docs/api/math/bounds/encapsulate.md new file mode 100644 index 0000000..5a18ed3 --- /dev/null +++ b/docs/api/math/bounds/encapsulate.md @@ -0,0 +1,21 @@ +# Bounds::Encapsulate + +```cpp +void Encapsulate(const Vector3& point) +void Encapsulate(const Bounds& bounds) +``` + +扩展包围盒以包含点或另一个 Bounds。 + +**参数:** +- `point` - 要包含的点 +- `bounds` - 要包含的 Bounds + +**复杂度:** O(1) + +**示例:** + +```cpp +bounds.Encapsulate(point); +bounds.Encapsulate(otherBounds); +``` diff --git a/docs/api/math/bounds/expand.md b/docs/api/math/bounds/expand.md new file mode 100644 index 0000000..e9f1458 --- /dev/null +++ b/docs/api/math/bounds/expand.md @@ -0,0 +1,19 @@ +# Bounds::Expand + +```cpp +void Expand(float amount) +void Expand(const Vector3& amount) +``` + +扩展包围盒。 + +**参数:** +- `amount` - 扩展量(各方向或统一) + +**复杂度:** O(1) + +**示例:** + +```cpp +bounds.Expand(1.0f); +``` diff --git a/docs/api/math/bounds/getclosestpoint.md b/docs/api/math/bounds/getclosestpoint.md new file mode 100644 index 0000000..96202ce --- /dev/null +++ b/docs/api/math/bounds/getclosestpoint.md @@ -0,0 +1,20 @@ +# Bounds::GetClosestPoint + +```cpp +Vector3 GetClosestPoint(const Vector3& point) const +``` + +获取包围盒上最接近给定点的点。 + +**参数:** +- `point` - 参考点 + +**返回:** `Vector3` - 盒上最接近的点 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 closest = bounds.GetClosestPoint(point); +``` diff --git a/docs/api/math/bounds/getmax.md b/docs/api/math/bounds/getmax.md new file mode 100644 index 0000000..c41e81d --- /dev/null +++ b/docs/api/math/bounds/getmax.md @@ -0,0 +1,17 @@ +# Bounds::GetMax + +```cpp +Vector3 GetMax() const +``` + +获取包围盒的最大点。 + +**返回:** `Vector3` - center + extents + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 max = bounds.GetMax(); +``` diff --git a/docs/api/math/bounds/getmin.md b/docs/api/math/bounds/getmin.md new file mode 100644 index 0000000..facd7ff --- /dev/null +++ b/docs/api/math/bounds/getmin.md @@ -0,0 +1,17 @@ +# Bounds::GetMin + +```cpp +Vector3 GetMin() const +``` + +获取包围盒的最小点。 + +**返回:** `Vector3` - center - extents + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 min = bounds.GetMin(); +``` diff --git a/docs/api/math/bounds/getvolume.md b/docs/api/math/bounds/getvolume.md new file mode 100644 index 0000000..32ad29f --- /dev/null +++ b/docs/api/math/bounds/getvolume.md @@ -0,0 +1,17 @@ +# Bounds::GetVolume + +```cpp +float GetVolume() const +``` + +计算包围盒的体积。 + +**返回:** `float` - 体积 + +**复杂度:** O(1) + +**示例:** + +```cpp +float vol = bounds.GetVolume(); +``` diff --git a/docs/api/math/bounds/intersects.md b/docs/api/math/bounds/intersects.md new file mode 100644 index 0000000..2bbb642 --- /dev/null +++ b/docs/api/math/bounds/intersects.md @@ -0,0 +1,20 @@ +# Bounds::Intersects + +```cpp +bool Intersects(const Bounds& other) const +``` + +检测两个 Bounds 是否相交。 + +**参数:** +- `other` - 另一个 Bounds + +**返回:** `bool` - true 表示相交 + +**复杂度:** O(1) + +**示例:** + +```cpp +if (bounds.Intersects(other)) { /* collision */ } +``` diff --git a/docs/api/math/bounds/setminmax.md b/docs/api/math/bounds/setminmax.md new file mode 100644 index 0000000..f575367 --- /dev/null +++ b/docs/api/math/bounds/setminmax.md @@ -0,0 +1,19 @@ +# Bounds::SetMinMax + +```cpp +void SetMinMax(const Vector3& min, const Vector3& max) +``` + +从最小/最大点设置包围盒。 + +**参数:** +- `min` - 最小点 +- `max` - 最大点 + +**复杂度:** O(1) + +**示例:** + +```cpp +bounds.SetMinMax(minPoint, maxPoint); +``` diff --git a/docs/api/math/box/box.md b/docs/api/math/box/box.md new file mode 100644 index 0000000..3f6952e --- /dev/null +++ b/docs/api/math/box/box.md @@ -0,0 +1,44 @@ +# Box + +带变换的包围盒结构体(支持 OBB 语义,取决于方法)。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 结构体定义 + +```cpp +struct Box { + Vector3 center = Vector3::Zero(); + Vector3 extents = Vector3::Zero(); + Matrix4x4 transform = Matrix4x4::Identity(); +}; +``` + +**成员:** +- `center` - 包围盒中心点 +- `extents` - 包围盒半长(各轴向的半径) +- `transform` - 变换矩阵(用于 OBB 检测) + +**注意:** `Contains` 方法会使用 `transform` 进行真正的 OBB 检测。`Intersects(Box)` 目前使用 AABB 简化算法,未考虑旋转。 + +## 构造函数 + +- `Box()` - 默认构造 +- `Box(const Vector3& center, const Vector3& extents)` - 从中心和半长构造 + +## 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [GetMin()](getmin.md) | `Vector3` | 局部空间最小点 | +| [GetMax()](getmax.md) | `Vector3` | 局部空间最大点 | +| [Contains(point)](contains.md) | `bool` | 点是否在盒内(使用 transform) | +| [Intersects(Sphere)](intersects.md) | `bool` | 与球体相交 | +| [Intersects(Box)](intersects-box.md) | `bool` | 与另一个盒相交(AABB 检测) | +| [Intersects(Ray, t)](intersects-ray.md) | `bool` | 与射线相交 | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/box/contains.md b/docs/api/math/box/contains.md new file mode 100644 index 0000000..3bac9af --- /dev/null +++ b/docs/api/math/box/contains.md @@ -0,0 +1,20 @@ +# Box::Contains + +```cpp +bool Contains(const Vector3& point) const +``` + +检测点是否在盒内。 + +**参数:** +- `point` - 要检测的点 + +**返回:** `bool` - true 表示点在盒内 + +**复杂度:** O(1) + +**示例:** + +```cpp +if (box.Contains(point)) { /* inside */ } +``` diff --git a/docs/api/math/box/getmax.md b/docs/api/math/box/getmax.md new file mode 100644 index 0000000..364e463 --- /dev/null +++ b/docs/api/math/box/getmax.md @@ -0,0 +1,17 @@ +# Box::GetMax + +```cpp +Vector3 GetMax() const +``` + +获取局部空间最大点。 + +**返回:** `Vector3` - (+extents) + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 max = box.GetMax(); +``` diff --git a/docs/api/math/box/getmin.md b/docs/api/math/box/getmin.md new file mode 100644 index 0000000..6b338b9 --- /dev/null +++ b/docs/api/math/box/getmin.md @@ -0,0 +1,17 @@ +# Box::GetMin + +```cpp +Vector3 GetMin() const +``` + +获取局部空间最小点。 + +**返回:** `Vector3` - (-extents) + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 min = box.GetMin(); +``` diff --git a/docs/api/math/box/intersects-box.md b/docs/api/math/box/intersects-box.md new file mode 100644 index 0000000..4bf9c5e --- /dev/null +++ b/docs/api/math/box/intersects-box.md @@ -0,0 +1,22 @@ +# Box::Intersects (Box) + +```cpp +bool Intersects(const Box& other) const +``` + +检测两个盒是否相交(使用 AABB 简化算法,暂未考虑 transform 旋转)。 + +**参数:** +- `other` - 另一个盒 + +**返回:** `bool` - true 表示相交 + +**注意:** 当前实现为 AABB 检测,未使用 transform 进行真正的 OBB-SAT 检测。 + +**复杂度:** O(1) + +**示例:** + +```cpp +if (box.Intersects(otherBox)) { /* collision */ } +``` diff --git a/docs/api/math/box/intersects-ray.md b/docs/api/math/box/intersects-ray.md new file mode 100644 index 0000000..7a4c05a --- /dev/null +++ b/docs/api/math/box/intersects-ray.md @@ -0,0 +1,24 @@ +# Box::Intersects (Ray) + +```cpp +bool Intersects(const Ray& ray, float& t) const +``` + +检测盒是否与射线相交。 + +**参数:** +- `ray` - 射线 +- `t` - 输出交点距离 + +**返回:** `bool` - true 表示相交 + +**复杂度:** O(1) + +**示例:** + +```cpp +float t; +if (box.Intersects(ray, t)) { + Vector3 hit = ray.GetPoint(t); +} +``` diff --git a/docs/api/math/box/intersects.md b/docs/api/math/box/intersects.md new file mode 100644 index 0000000..d536651 --- /dev/null +++ b/docs/api/math/box/intersects.md @@ -0,0 +1,20 @@ +# Box::Intersects + +```cpp +bool Intersects(const Sphere& sphere) const +``` + +检测盒是否与球体相交。 + +**参数:** +- `sphere` - 球体 + +**返回:** `bool` - true 表示相交 + +**复杂度:** O(1) + +**示例:** + +```cpp +if (box.Intersects(sphere)) { /* collision */ } +``` diff --git a/docs/api/math/color/black.md b/docs/api/math/color/black.md new file mode 100644 index 0000000..002486c --- /dev/null +++ b/docs/api/math/color/black.md @@ -0,0 +1,11 @@ +# Color::Black + +```cpp +static Color Black() +``` + +返回黑色 (0, 0, 0, 1)。 + +**返回:** `Color` + +**示例:** `Color c = Color::Black();` diff --git a/docs/api/math/color/blue.md b/docs/api/math/color/blue.md new file mode 100644 index 0000000..382790f --- /dev/null +++ b/docs/api/math/color/blue.md @@ -0,0 +1,11 @@ +# Color::Blue + +```cpp +static Color Blue() +``` + +返回蓝色 (0, 0, 1, 1)。 + +**返回:** `Color` + +**示例:** `Color c = Color::Blue();` diff --git a/docs/api/math/color/clear.md b/docs/api/math/color/clear.md new file mode 100644 index 0000000..ff5fc2f --- /dev/null +++ b/docs/api/math/color/clear.md @@ -0,0 +1,11 @@ +# Color::Clear + +```cpp +static Color Clear() +``` + +返回透明黑色 (0, 0, 0, 0)。 + +**返回:** `Color` + +**示例:** `Color c = Color::Clear();` diff --git a/docs/api/math/color/color.md b/docs/api/math/color/color.md new file mode 100644 index 0000000..de20d2c --- /dev/null +++ b/docs/api/math/color/color.md @@ -0,0 +1,64 @@ +# Color + +颜色结构体,支持 RGBA 浮点分量。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 结构体定义 + +```cpp +struct Color { + float r = 1.0f; + float g = 1.0f; + float b = 1.0f; + float a = 1.0f; +}; +``` + +## 构造函数 + +- `Color()` - 默认构造,初始化为白色 (1, 1, 1, 1) +- `constexpr Color(float r, float g, float b, float a = 1.0f)` - 从 RGBA 分量构造 + +## 静态工厂方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [White()](white.md) | `Color` | (1, 1, 1, 1) | +| [Black()](black.md) | `Color` | (0, 0, 0, 1) | +| [Red()](red.md) | `Color` | (1, 0, 0, 1) | +| [Green()](green.md) | `Color` | (0, 1, 0, 1) | +| [Blue()](blue.md) | `Color` | (0, 0, 1, 1) | +| [Yellow()](yellow.md) | `Color` | (1, 1, 0, 1) | +| [Cyan()](cyan.md) | `Color` | (0, 1, 1, 1) | +| [Magenta()](magenta.md) | `Color` | (1, 0, 1, 1) | +| [Clear()](clear.md) | `Color` | (0, 0, 0, 0),透明黑 | + +## 静态方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Lerp(a, b, t)](lerp.md) | `Color` | 颜色线性插值 | + +## 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [ToRGBA()](torgba.md) | `uint32_t` | 转换为 32-bit RGBA (0xRRGGBBAA) | +| [ToVector3()](tovector3.md) | `Vector3` | 转换为 RGB (丢弃 alpha) | +| [ToVector4()](tovector4.md) | `Vector4` | 转换为 RGBA | + +## 运算符 + +| 运算符 | 描述 | +|--------|------| +| `operator+(Color, Color)` | 颜色相加 | +| `operator-(Color, Color)` | 颜色相减 | +| `operator*(Color, float)` | 颜色乘以标量 | +| `operator/(Color, float)` | 颜色除以标量 | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/color/cyan.md b/docs/api/math/color/cyan.md new file mode 100644 index 0000000..e805190 --- /dev/null +++ b/docs/api/math/color/cyan.md @@ -0,0 +1,11 @@ +# Color::Cyan + +```cpp +static Color Cyan() +``` + +返回青色 (0, 1, 1, 1)。 + +**返回:** `Color` + +**示例:** `Color c = Color::Cyan();` diff --git a/docs/api/math/color/green.md b/docs/api/math/color/green.md new file mode 100644 index 0000000..009484b --- /dev/null +++ b/docs/api/math/color/green.md @@ -0,0 +1,11 @@ +# Color::Green + +```cpp +static Color Green() +``` + +返回绿色 (0, 1, 0, 1)。 + +**返回:** `Color` + +**示例:** `Color c = Color::Green();` diff --git a/docs/api/math/color/lerp.md b/docs/api/math/color/lerp.md new file mode 100644 index 0000000..82f3574 --- /dev/null +++ b/docs/api/math/color/lerp.md @@ -0,0 +1,22 @@ +# Color::Lerp + +```cpp +static Color Lerp(const Color& a, const Color& b, float t) +``` + +在两个颜色之间进行线性插值。 + +**参数:** +- `a` - 起始颜色 +- `b` - 结束颜色 +- `t` - 插值因子 (0-1) + +**返回:** `Color` - 插值结果 + +**复杂度:** O(1) + +**示例:** + +```cpp +Color lerped = Color::Lerp(Color::Red(), Color::Blue(), 0.5f); +``` diff --git a/docs/api/math/color/magenta.md b/docs/api/math/color/magenta.md new file mode 100644 index 0000000..68b1081 --- /dev/null +++ b/docs/api/math/color/magenta.md @@ -0,0 +1,11 @@ +# Color::Magenta + +```cpp +static Color Magenta() +``` + +返回品红色 (1, 0, 1, 1)。 + +**返回:** `Color` + +**示例:** `Color c = Color::Magenta();` diff --git a/docs/api/math/color/red.md b/docs/api/math/color/red.md new file mode 100644 index 0000000..ea81800 --- /dev/null +++ b/docs/api/math/color/red.md @@ -0,0 +1,11 @@ +# Color::Red + +```cpp +static Color Red() +``` + +返回红色 (1, 0, 0, 1)。 + +**返回:** `Color` + +**示例:** `Color c = Color::Red();` diff --git a/docs/api/math/color/torgba.md b/docs/api/math/color/torgba.md new file mode 100644 index 0000000..ce9f5ef --- /dev/null +++ b/docs/api/math/color/torgba.md @@ -0,0 +1,18 @@ +# Color::ToRGBA + +```cpp +uint32_t ToRGBA() const +``` + +将颜色转换为 32-bit RGBA 整数格式。 + +**返回:** `uint32_t` - RGBA 值 (0xRRGGBBAA) + +**复杂度:** O(1) + +**示例:** + +```cpp +Color c(1.0f, 0.0f, 0.0f, 1.0f); +uint32_t rgba = c.ToRGBA(); +``` diff --git a/docs/api/math/color/tovector3.md b/docs/api/math/color/tovector3.md new file mode 100644 index 0000000..ea9b3be --- /dev/null +++ b/docs/api/math/color/tovector3.md @@ -0,0 +1,17 @@ +# Color::ToVector3 + +```cpp +Vector3 ToVector3() const +``` + +将颜色转换为 Vector3(丢弃 alpha)。 + +**返回:** `Vector3` - RGB 值 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 rgb = Color::Red().ToVector3(); +``` diff --git a/docs/api/math/color/tovector4.md b/docs/api/math/color/tovector4.md new file mode 100644 index 0000000..d7bfdd3 --- /dev/null +++ b/docs/api/math/color/tovector4.md @@ -0,0 +1,17 @@ +# Color::ToVector4 + +```cpp +Vector4 ToVector4() const +``` + +将颜色转换为 Vector4。 + +**返回:** `Vector4` - RGBA 值 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector4 rgba = Color::Red().ToVector4(); +``` diff --git a/docs/api/math/color/white.md b/docs/api/math/color/white.md new file mode 100644 index 0000000..5247210 --- /dev/null +++ b/docs/api/math/color/white.md @@ -0,0 +1,11 @@ +# Color::White + +```cpp +static Color White() +``` + +返回白色 (1, 1, 1, 1)。 + +**返回:** `Color` + +**示例:** `Color c = Color::White();` diff --git a/docs/api/math/color/yellow.md b/docs/api/math/color/yellow.md new file mode 100644 index 0000000..46a349f --- /dev/null +++ b/docs/api/math/color/yellow.md @@ -0,0 +1,11 @@ +# Color::Yellow + +```cpp +static Color Yellow() +``` + +返回黄色 (1, 1, 0, 1)。 + +**返回:** `Color` + +**示例:** `Color c = Color::Yellow();` diff --git a/docs/api/math/frustum/contains-bounds.md b/docs/api/math/frustum/contains-bounds.md new file mode 100644 index 0000000..8a0da23 --- /dev/null +++ b/docs/api/math/frustum/contains-bounds.md @@ -0,0 +1,25 @@ +# Frustum::Contains (bounds) + +```cpp +bool Contains(const Bounds& bounds) const +``` + +检测轴对齐包围盒是否完全在视锥体内。 + +**参数:** +- `bounds` - 要检测的轴对齐包围盒 + +**返回:** `bool` - Bounds 完全在视锥内返回 true + +**复杂度:** O(1) + +**示例:** + +```cpp +Frustum frustum = camera.CalculateFrustum(); +Bounds objectBounds = object.GetWorldBounds(); +if (frustum.Contains(objectBounds)) { + // 包围盒完全在视锥内,需要渲染 + Render(object); +} +``` diff --git a/docs/api/math/frustum/contains-point.md b/docs/api/math/frustum/contains-point.md new file mode 100644 index 0000000..d72ee37 --- /dev/null +++ b/docs/api/math/frustum/contains-point.md @@ -0,0 +1,24 @@ +# Frustum::Contains (point) + +```cpp +bool Contains(const Vector3& point) const +``` + +检测点是否在视锥体内。 + +**参数:** +- `point` - 要检测的世界空间点 + +**返回:** `bool` - 点在视锥内返回 true + +**复杂度:** O(1) + +**示例:** + +```cpp +Frustum frustum = camera.CalculateFrustum(); +Vector3 point = object.GetPosition(); +if (frustum.Contains(point)) { + // 点在视锥内 +} +``` diff --git a/docs/api/math/frustum/contains-sphere.md b/docs/api/math/frustum/contains-sphere.md new file mode 100644 index 0000000..569522b --- /dev/null +++ b/docs/api/math/frustum/contains-sphere.md @@ -0,0 +1,24 @@ +# Frustum::Contains (sphere) + +```cpp +bool Contains(const Sphere& sphere) const +``` + +检测球体是否完全在视锥体内。 + +**参数:** +- `sphere` - 要检测的球体 + +**返回:** `bool` - 球体完全在视锥内返回 true + +**复杂度:** O(1) + +**示例:** + +```cpp +Frustum frustum = camera.CalculateFrustum(); +Sphere collider = object.GetBoundingSphere(); +if (frustum.Contains(collider)) { + // 球体完全在视锥内 +} +``` diff --git a/docs/api/math/frustum/frustum.md b/docs/api/math/frustum/frustum.md new file mode 100644 index 0000000..cd24d4b --- /dev/null +++ b/docs/api/math/frustum/frustum.md @@ -0,0 +1,45 @@ +# Frustum + +视锥体,用于视锥剔除。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 类定义 + +```cpp +class Frustum { +public: + Plane planes[6]; + + enum class PlaneIndex { + Left = 0, + Right = 1, + Bottom = 2, + Top = 3, + Near = 4, + Far = 5 + }; + + bool Contains(const Vector3& point) const; + bool Contains(const Sphere& sphere) const; + bool Contains(const Bounds& bounds) const; + bool Intersects(const Bounds& bounds) const; + bool Intersects(const Sphere& sphere) const; +}; +``` + +## 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Contains(point)](contains-point.md) | `bool` | 点是否在视锥内 | +| [Contains(sphere)](contains-sphere.md) | `bool` | 球体是否完全在视锥内 | +| [Contains(bounds)](contains-bounds.md) | `bool` | Bounds 是否完全在视锥内 | +| [Intersects(bounds)](intersects-bounds.md) | `bool` | Bounds 是否与视锥相交 | +| [Intersects(sphere)](intersects-sphere.md) | `bool` | 球体是否与视锥相交 | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/frustum/intersects-bounds.md b/docs/api/math/frustum/intersects-bounds.md new file mode 100644 index 0000000..d4be870 --- /dev/null +++ b/docs/api/math/frustum/intersects-bounds.md @@ -0,0 +1,26 @@ +# Frustum::Intersects (bounds) + +```cpp +bool Intersects(const Bounds& bounds) const +``` + +检测轴对齐包围盒是否与视锥体相交。 + +**参数:** +- `bounds` - 要检测的轴对齐包围盒 + +**返回:** `bool` - 与视锥相交返回 true + +**复杂度:** O(1) + +**示例:** + +```cpp +Frustum frustum = camera.CalculateFrustum(); +for (const auto& object : sceneObjects) { + if (frustum.Intersects(object.bounds)) { + // 物体与视锥相交,需要渲染 + Render(object); + } +} +``` diff --git a/docs/api/math/frustum/intersects-sphere.md b/docs/api/math/frustum/intersects-sphere.md new file mode 100644 index 0000000..363b2ec --- /dev/null +++ b/docs/api/math/frustum/intersects-sphere.md @@ -0,0 +1,25 @@ +# Frustum::Intersects (sphere) + +```cpp +bool Intersects(const Sphere& sphere) const +``` + +检测球体是否与视锥体相交。 + +**参数:** +- `sphere` - 要检测的球体 + +**返回:** `bool` - 与视锥相交返回 true + +**复杂度:** O(1) + +**示例:** + +```cpp +Frustum frustum = camera.CalculateFrustum(); +Sphere collider = object.GetBoundingSphere(); +if (frustum.Intersects(collider)) { + // 球体与视锥相交 + Render(object); +} +``` diff --git a/docs/api/math/h/deg-to-rad.md b/docs/api/math/h/deg-to-rad.md new file mode 100644 index 0000000..9e18d43 --- /dev/null +++ b/docs/api/math/h/deg-to-rad.md @@ -0,0 +1,20 @@ +# Math::DEG_TO_RAD + +```cpp +constexpr float DEG_TO_RAD = Math::PI / 180.0f; +``` + +`DEG_TO_RAD` 是角度转弧度的转换系数。1 度等于 `PI / 180` 弧度,约等于 0.01745329251994329577。使用该常量将角度值乘以 `DEG_TO_RAD` 即可得到对应的弧度值。 + +**示例:** + +```cpp +#include + +float angleDegrees = 90.0f; +float angleRadians = angleDegrees * Math::DEG_TO_RAD; +``` + +## 相关文档 + +- [Math 总览](h.md) - 返回 Math 概览 diff --git a/docs/api/math/h/degrees.md b/docs/api/math/h/degrees.md new file mode 100644 index 0000000..2d2c2e6 --- /dev/null +++ b/docs/api/math/h/degrees.md @@ -0,0 +1,20 @@ +# Math::Degrees + +```cpp +float Degrees(float radians); +``` + +`Degrees` 函数将弧度值转换为角度值。转换公式为:`角度 = 弧度 * (180 / PI)`。该函数是 `Radians` 函数的逆函数,常用于将三角函数的返回值或物理引擎中的弧度值转换为人机界面友好的角度值。 + +**示例:** + +```cpp +#include + +float radians = Math::HALF_PI; +float degrees = Math::Degrees(radians); +``` + +## 相关文档 + +- [Math 总览](h.md) - 返回 Math 概览 diff --git a/docs/api/math/h/epsilon.md b/docs/api/math/h/epsilon.md new file mode 100644 index 0000000..0720ef6 --- /dev/null +++ b/docs/api/math/h/epsilon.md @@ -0,0 +1,23 @@ +# Math::EPSILON + +```cpp +constexpr float EPSILON = 1e-6f; +``` + +`EPSILON` 是一个非常小的浮点数常量,值为 0.000001。该常量主要用于浮点数比较,由于浮点数精度问题,直接使用 `==` 比较浮点数可能产生错误结果,此时应使用 `EPSILON` 进行容差比较。例如判断两个浮点数是否相等,可以检查它们的差的绝对值是否小于 `EPSILON`。 + +**示例:** + +```cpp +#include + +float a = 0.1f + 0.2f; +float b = 0.3f; +if (Math::Abs(a - b) < Math::EPSILON) { + // a 和 b 可以视为相等 +} +``` + +## 相关文档 + +- [Math 总览](h.md) - 返回 Math 概览 diff --git a/docs/api/math/h/float-max.md b/docs/api/math/h/float-max.md new file mode 100644 index 0000000..510b187 --- /dev/null +++ b/docs/api/math/h/float-max.md @@ -0,0 +1,19 @@ +# Math::FLOAT_MAX + +```cpp +constexpr float FLOAT_MAX = 3.402823466e+38f; +``` + +`FLOAT_MAX` 是 IEEE 754 单精度浮点数能表示的最大正有限值,约为 3.402823466e+38。该常量常用于初始化变量为最大值、在搜索算法中作为上界、或在需要表示"无穷大"但又不想引入 `INFINITY` 的场景中使用。 + +**示例:** + +```cpp +#include + +float maxDistance = Math::FLOAT_MAX; +``` + +## 相关文档 + +- [Math 总览](h.md) - 返回 Math 概览 diff --git a/docs/api/math/h/h.md b/docs/api/math/h/h.md new file mode 100644 index 0000000..08f84b4 --- /dev/null +++ b/docs/api/math/h/h.md @@ -0,0 +1,54 @@ +# Math + +**命名空间**: `XCEngine::Math` + +**类型**: `header` + +**描述**: 数学库常量和辅助函数头文件。 + +## 概述 + +`Math.h` 提供了图形引擎常用的数学常量和辅助函数,包括圆周率、角度转换、浮点精度等基础常量,以及角度弧度转换等常用函数。 + +## 常量 + +| 常量 | 值 | 描述 | +|------|-----|------| +| [PI](pi.md) | 3.14159265358979323846f | 圆周率 | +| [TWO_PI](two-pi.md) | 6.28318530717958647692f | 2π | +| [HALF_PI](half-pi.md) | 1.57079632679489661923f | π/2 | +| [DEG_TO_RAD](deg-to-rad.md) | PI / 180.0f | 度到弧度 | +| [RAD_TO_DEG](rad-to-deg.md) | 180.0f / PI | 弧度到度 | +| [EPSILON](epsilon.md) | 1e-6f | 浮点精度 | +| [FLOAT_MAX](float-max.md) | 3.402823466e+38f | 浮点最大值 | + +## 辅助函数 + +| 函数 | 描述 | +|------|------| +| [Radians](radians.md) | 度转弧度 | +| [Degrees](degrees.md) | 弧度转度 | + +## 使用示例 + +```cpp +#include + +using namespace XCEngine::Math; + +// 使用常量 +float angle = 90.0f * DEG_TO_RAD; // 90度转弧度 + +// 使用函数 +float rad = Radians(180.0f); // 180度 -> π 弧度 +float deg = Degrees(Math::PI); // π 弧度 -> 180度 + +// 比较浮点数 +if (fabsf(a - b) < EPSILON) { + // 认为 a 和 b 相等 +} +``` + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/h/half-pi.md b/docs/api/math/h/half-pi.md new file mode 100644 index 0000000..2a6f8cd --- /dev/null +++ b/docs/api/math/h/half-pi.md @@ -0,0 +1,19 @@ +# Math::HALF_PI + +```cpp +constexpr float HALF_PI = 1.57079632679489661923f; +``` + +`HALF_PI` 是圆周率除以 2,即 90 度对应的弧度值,约为 1.57079632679489661923。该常量常用于角度与弧度的转换、四分之一圆周计算等场景。 + +**示例:** + +```cpp +#include + +float ninetyDegreesRadians = Math::HALF_PI; +``` + +## 相关文档 + +- [Math 总览](h.md) - 返回 Math 概览 diff --git a/docs/api/math/h/pi.md b/docs/api/math/h/pi.md new file mode 100644 index 0000000..a40653a --- /dev/null +++ b/docs/api/math/h/pi.md @@ -0,0 +1,22 @@ +# Math::PI + +```cpp +constexpr float PI = 3.14159265358979323846f; +``` + +圆周率常量,精确到 float 能表示的最高精度。 + +**用途:** 用于三角函数计算、弧度角度转换、圆形/弧度相关计算。 + +**示例:** + +```cpp +#include + +float circumference = 2.0f * Math::PI * radius; +float area = Math::PI * radius * radius; +``` + +## 相关文档 + +- [Math 总览](h.md) - 返回 Math 概览 diff --git a/docs/api/math/h/rad-to-deg.md b/docs/api/math/h/rad-to-deg.md new file mode 100644 index 0000000..ab50c13 --- /dev/null +++ b/docs/api/math/h/rad-to-deg.md @@ -0,0 +1,20 @@ +# Math::RAD_TO_DEG + +```cpp +constexpr float RAD_TO_DEG = 180.0f / Math::PI; +``` + +`RAD_TO_DEG` 是弧度转角度的转换系数。1 弧度等于 `180 / PI` 度,约等于 57.29577951308232087685。使用该常量将弧度值乘以 `RAD_TO_DEG` 即可得到对应的角度值。 + +**示例:** + +```cpp +#include + +float radians = Math::HALF_PI; +float degrees = radians * Math::RAD_TO_DEG; +``` + +## 相关文档 + +- [Math 总览](h.md) - 返回 Math 概览 diff --git a/docs/api/math/h/radians.md b/docs/api/math/h/radians.md new file mode 100644 index 0000000..a1c7077 --- /dev/null +++ b/docs/api/math/h/radians.md @@ -0,0 +1,20 @@ +# Math::Radians + +```cpp +float Radians(float degrees); +``` + +`Radians` 函数将角度值转换为弧度值。转换公式为:`弧度 = 角度 * (PI / 180)`。该函数是 `Degrees` 函数的逆函数,常用于将 UI 输入的角度值或游戏中的角度值转换为三角函数所需的弧度值。 + +**示例:** + +```cpp +#include + +float degrees = 90.0f; +float radians = Math::Radians(degrees); +``` + +## 相关文档 + +- [Math 总览](h.md) - 返回 Math 概览 diff --git a/docs/api/math/h/two-pi.md b/docs/api/math/h/two-pi.md new file mode 100644 index 0000000..1efd8bc --- /dev/null +++ b/docs/api/math/h/two-pi.md @@ -0,0 +1,19 @@ +# Math::TWO_PI + +```cpp +constexpr float TWO_PI = 6.28318530717958647692f; +``` + +`TWO_PI` 是圆周率的两倍,即完整的圆周长对应的弧度值,约为 6.28318530717958647692。该常量常用于需要完整圆周旋转的场景,例如角度归一化、三角函数周期计算、圆形运动等。 + +**示例:** + +```cpp +#include + +float fullCircleRadians = Math::TWO_PI; +``` + +## 相关文档 + +- [Math 总览](h.md) - 返回 Math 概览 diff --git a/docs/api/math/math.md b/docs/api/math/math.md new file mode 100644 index 0000000..acab94b --- /dev/null +++ b/docs/api/math/math.md @@ -0,0 +1,100 @@ +# Math 模块概览 + +**命名空间**: `XCEngine::Math` + +**类型**: `module` + +**描述**: XCEngine 的数学库模块,提供图形引擎常用的数学类型和函数。 + +## 概述 + +Math 模块提供了一套完整的图形数学库,包括向量、矩阵、四元数、变换和几何类型等。 + +## 模块内容 + +### 向量类型 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [Vector2](vector2/vector2.md) | `Vector2.h` | 二维向量 | +| [Vector3](vector3/vector3.md) | `Vector3.h` | 三维向量 | +| [Vector4](vector4/vector4.md) | `Vector4.h` | 四维向量 | + +### 矩阵类型 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [Matrix3](matrix3/matrix3.md) | `Matrix3.h` | 3x3 矩阵 | +| [Matrix4](matrix4/matrix4.md) | `Matrix4.h` | 4x4 矩阵 | + +### 旋转/变换 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [Quaternion](quaternion/quaternion.md) | `Quaternion.h` | 四元数 | +| [Transform](transform/transform.md) | `Transform.h` | 变换组件 | + +### 几何类型 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [Color](color/color.md) | `Color.h` | 颜色 | +| [Ray](ray/ray.md) | `Ray.h` | 射线 | +| [Plane](plane/plane.md) | `Plane.h` | 平面 | +| [Sphere](sphere/sphere.md) | `Sphere.h` | 球体 | +| [Box](box/box.md) | `Box.h` | 盒子 | +| [Bounds](bounds/bounds.md) | `Bounds.h` | 包围盒 | +| [AABB](aabb/aabb.md) | `AABB.h` | 轴对齐包围盒 | +| [Frustum](frustum/frustum.md) | `Frustum.h` | 视锥体 | +| [Rect](rect/rect.md) | `Rect.h` | 二维矩形 | + +## 常量定义 + +| 常量 | 值 | 描述 | +|------|-----|------| +| `PI` | 3.14159265358979323846f | 圆周率 | +| `TWO_PI` | 6.28318530717958647692f | 2π | +| `HALF_PI` | 1.57079632679489661923f | π/2 | +| `DEG_TO_RAD` | PI / 180.0f | 度到弧度 | +| `RAD_TO_DEG` | 180.0f / PI | 弧度到度 | +| `EPSILON` | 1e-6f | 浮点精度 | +| `FLOAT_MAX` | 3.402823466e+38f | 浮点最大值 | + +详细文档: [Math.h - 常量和辅助函数](h/h.md) + +## 辅助函数 + +| 函数 | 描述 | +|------|------| +| `Radians(float degrees)` | 度转弧度 | +| `Degrees(float radians)` | 弧度转度 | + +## 使用示例 + +```cpp +#include +#include +#include +#include + +using namespace XCEngine::Math; + +// 向量运算 +Vector3 a(1.0f, 0.0f, 0.0f); +Vector3 b(0.0f, 1.0f, 0.0f); +float dot = Vector3::Dot(a, b); +Vector3 cross = Vector3::Cross(a, b); +Vector3 normalized = Vector3::Normalize(a); + +// 矩阵运算 +Matrix4 model = Matrix4::TRS(position, rotation, scale); +Matrix4 view = Matrix4::LookAt(eye, target, up); +Matrix4 projection = Matrix4::Perspective(fov, aspect, near, far); +Matrix4 mvp = projection * view * model; + +// 四元数运算 +Quaternion q1 = Quaternion::FromEulerAngles(0, 90 * DEG_TO_RAD, 0); +Quaternion q2 = Quaternion::FromAxisAngle(Vector3::Up(), Math::Radians(45.0f)); +Quaternion combined = q1 * q2; +Vector3 rotated = q2 * Vector3::Forward(); +``` diff --git a/docs/api/math/matrix3/determinant.md b/docs/api/math/matrix3/determinant.md new file mode 100644 index 0000000..6d237fa --- /dev/null +++ b/docs/api/math/matrix3/determinant.md @@ -0,0 +1,18 @@ +# Matrix3::Determinant + +```cpp +float Determinant() const +``` + +计算矩阵的行列式。 + +**返回:** `float` - 行列式值 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix3 mat = ...; +float det = mat.Determinant(); +``` diff --git a/docs/api/math/matrix3/identity.md b/docs/api/math/matrix3/identity.md new file mode 100644 index 0000000..e32fcfd --- /dev/null +++ b/docs/api/math/matrix3/identity.md @@ -0,0 +1,17 @@ +# Matrix3::Identity + +```cpp +static Matrix3 Identity() +``` + +返回 3x3 单位矩阵。 + +**返回:** `Matrix3` - 单位矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix3 identity = Matrix3::Identity(); +``` diff --git a/docs/api/math/matrix3/inverse.md b/docs/api/math/matrix3/inverse.md new file mode 100644 index 0000000..3a3b05c --- /dev/null +++ b/docs/api/math/matrix3/inverse.md @@ -0,0 +1,18 @@ +# Matrix3::Inverse + +```cpp +Matrix3 Inverse() const +``` + +返回矩阵的逆矩阵。 + +**返回:** `Matrix3` - 逆矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix3 mat = ...; +Matrix3 inv = mat.Inverse(); +``` diff --git a/docs/api/math/matrix3/matrix3.md b/docs/api/math/matrix3/matrix3.md new file mode 100644 index 0000000..ebeab7e --- /dev/null +++ b/docs/api/math/matrix3/matrix3.md @@ -0,0 +1,57 @@ +# Matrix3 / Matrix3x3 + +3x3 矩阵结构体,用于表示 3D 旋转和缩放变换。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 类型别名 + +```cpp +using Matrix3 = Matrix3x3; +``` + +## 存储方式 + +行优先存储 (row-major): +``` +m[row][col] +m[0][0] m[0][1] m[0][2] +m[1][0] m[1][1] m[1][2] +m[2][0] m[2][1] m[2][2] +``` + +## 构造函数 + +- 默认构造函数初始化为零矩阵 + +## 静态工厂方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Identity()](identity.md) | `Matrix3` | 单位矩阵 | +| [Zero()](zero.md) | `Matrix3` | 零矩阵 | +| [RotationX(radians)](rotationx.md) | `Matrix3` | X 轴旋转矩阵 | +| [RotationY(radians)](rotationy.md) | `Matrix3` | Y 轴旋转矩阵 | +| [RotationZ(radians)](rotationz.md) | `Matrix3` | Z 轴旋转矩阵 | +| [Scale(scale)](scale.md) | `Matrix3` | 缩放矩阵 | + +## 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Transpose()](transpose.md) | `Matrix3` | 转置矩阵 | +| [Inverse()](inverse.md) | `Matrix3` | 逆矩阵 | +| [Determinant()](determinant.md) | `float` | 行列式 | + +## 运算符 + +| 运算符 | 描述 | +|--------|------| +| `operator*(Matrix3, Matrix3)` | 矩阵乘法 | +| `operator*(Matrix3, Vector3)` | 矩阵-向量乘法 | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/matrix3/rotationx.md b/docs/api/math/matrix3/rotationx.md new file mode 100644 index 0000000..90888bb --- /dev/null +++ b/docs/api/math/matrix3/rotationx.md @@ -0,0 +1,20 @@ +# Matrix3::RotationX + +```cpp +static Matrix3 RotationX(float radians) +``` + +创建绕 X 轴旋转的矩阵。 + +**参数:** +- `radians` - 旋转角度(弧度) + +**返回:** `Matrix3` - 旋转矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix3 rotX = Matrix3::RotationX(Math::HALF_PI); +``` diff --git a/docs/api/math/matrix3/rotationy.md b/docs/api/math/matrix3/rotationy.md new file mode 100644 index 0000000..3874843 --- /dev/null +++ b/docs/api/math/matrix3/rotationy.md @@ -0,0 +1,20 @@ +# Matrix3::RotationY + +```cpp +static Matrix3 RotationY(float radians) +``` + +创建绕 Y 轴旋转的矩阵。 + +**参数:** +- `radians` - 旋转角度(弧度) + +**返回:** `Matrix3` - 旋转矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix3 rotY = Matrix3::RotationY(Math::HALF_PI); +``` diff --git a/docs/api/math/matrix3/rotationz.md b/docs/api/math/matrix3/rotationz.md new file mode 100644 index 0000000..2626ee4 --- /dev/null +++ b/docs/api/math/matrix3/rotationz.md @@ -0,0 +1,20 @@ +# Matrix3::RotationZ + +```cpp +static Matrix3 RotationZ(float radians) +``` + +创建绕 Z 轴旋转的矩阵。 + +**参数:** +- `radians` - 旋转角度(弧度) + +**返回:** `Matrix3` - 旋转矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix3 rotZ = Matrix3::RotationZ(Math::HALF_PI); +``` diff --git a/docs/api/math/matrix3/scale.md b/docs/api/math/matrix3/scale.md new file mode 100644 index 0000000..bcb6e7a --- /dev/null +++ b/docs/api/math/matrix3/scale.md @@ -0,0 +1,20 @@ +# Matrix3::Scale + +```cpp +static Matrix3 Scale(const Vector3& scale) +``` + +创建缩放矩阵。 + +**参数:** +- `scale` - 各轴缩放因子 + +**返回:** `Matrix3` - 缩放矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix3 scale = Matrix3::Scale(Vector3(2.0f, 2.0f, 2.0f)); +``` diff --git a/docs/api/math/matrix3/transpose.md b/docs/api/math/matrix3/transpose.md new file mode 100644 index 0000000..5c29068 --- /dev/null +++ b/docs/api/math/matrix3/transpose.md @@ -0,0 +1,18 @@ +# Matrix3::Transpose + +```cpp +Matrix3 Transpose() const +``` + +返回矩阵的转置。 + +**返回:** `Matrix3` - 转置矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix3 mat = ...; +Matrix3 transposed = mat.Transpose(); +``` diff --git a/docs/api/math/matrix3/zero.md b/docs/api/math/matrix3/zero.md new file mode 100644 index 0000000..4570904 --- /dev/null +++ b/docs/api/math/matrix3/zero.md @@ -0,0 +1,17 @@ +# Matrix3::Zero + +```cpp +static Matrix3 Zero() +``` + +返回零矩阵。 + +**返回:** `Matrix3` - 零矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix3 zero = Matrix3::Zero(); +``` diff --git a/docs/api/math/matrix4/decompose.md b/docs/api/math/matrix4/decompose.md new file mode 100644 index 0000000..3173c5c --- /dev/null +++ b/docs/api/math/matrix4/decompose.md @@ -0,0 +1,24 @@ +# Matrix4::Decompose + +```cpp +void Decompose(Vector3& translation, Quaternion& rotation, Vector3& scale) const +``` + +将矩阵分解为平移、旋转和缩放分量。 + +**参数:** +- `translation` - 输出平移向量 +- `rotation` - 输出旋转四元数 +- `scale` - 输出缩放向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 m = ...; +Vector3 translation; +Quaternion rotation; +Vector3 scale; +m.Decompose(translation, rotation, scale); +``` diff --git a/docs/api/math/matrix4/determinant.md b/docs/api/math/matrix4/determinant.md new file mode 100644 index 0000000..52ca8ac --- /dev/null +++ b/docs/api/math/matrix4/determinant.md @@ -0,0 +1,18 @@ +# Matrix4::Determinant + +```cpp +float Determinant() const +``` + +计算矩阵的行列式。 + +**返回:** `float` - 行列式值 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 m = ...; +float det = m.Determinant(); +``` diff --git a/docs/api/math/matrix4/getrotation.md b/docs/api/math/matrix4/getrotation.md new file mode 100644 index 0000000..720a756 --- /dev/null +++ b/docs/api/math/matrix4/getrotation.md @@ -0,0 +1,18 @@ +# Matrix4::GetRotation + +```cpp +Quaternion GetRotation() const +``` + +从矩阵中提取旋转分量。 + +**返回:** `Quaternion` - 旋转四元数 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 m = ...; +Quaternion rotation = m.GetRotation(); +``` diff --git a/docs/api/math/matrix4/getscale.md b/docs/api/math/matrix4/getscale.md new file mode 100644 index 0000000..660ec64 --- /dev/null +++ b/docs/api/math/matrix4/getscale.md @@ -0,0 +1,18 @@ +# Matrix4::GetScale + +```cpp +Vector3 GetScale() const +``` + +从矩阵中提取缩放分量。 + +**返回:** `Vector3` - 缩放向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 m = ...; +Vector3 scale = m.GetScale(); +``` diff --git a/docs/api/math/matrix4/gettranslation.md b/docs/api/math/matrix4/gettranslation.md new file mode 100644 index 0000000..adede5d --- /dev/null +++ b/docs/api/math/matrix4/gettranslation.md @@ -0,0 +1,18 @@ +# Matrix4::GetTranslation + +```cpp +Vector3 GetTranslation() const +``` + +从矩阵中提取平移分量。 + +**返回:** `Vector3` - 平移向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 m = ...; +Vector3 translation = m.GetTranslation(); +``` diff --git a/docs/api/math/matrix4/identity.md b/docs/api/math/matrix4/identity.md new file mode 100644 index 0000000..5609574 --- /dev/null +++ b/docs/api/math/matrix4/identity.md @@ -0,0 +1,17 @@ +# Matrix4::Identity + +```cpp +static Matrix4 Identity() +``` + +返回 4x4 单位矩阵。 + +**返回:** `Matrix4` - 单位矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 identity = Matrix4::Identity(); +``` diff --git a/docs/api/math/matrix4/inverse.md b/docs/api/math/matrix4/inverse.md new file mode 100644 index 0000000..a0ce7f5 --- /dev/null +++ b/docs/api/math/matrix4/inverse.md @@ -0,0 +1,18 @@ +# Matrix4::Inverse + +```cpp +Matrix4 Inverse() const +``` + +返回矩阵的逆矩阵。 + +**返回:** `Matrix4` - 逆矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 m = ...; +Matrix4 inv = m.Inverse(); +``` diff --git a/docs/api/math/matrix4/lookat.md b/docs/api/math/matrix4/lookat.md new file mode 100644 index 0000000..d8e8d00 --- /dev/null +++ b/docs/api/math/matrix4/lookat.md @@ -0,0 +1,22 @@ +# Matrix4::LookAt + +```cpp +static Matrix4 LookAt(const Vector3& eye, const Vector3& target, const Vector3& up) +``` + +创建视图矩阵(观察矩阵)。 + +**参数:** +- `eye` - 相机位置 +- `target` - 观察目标点 +- `up` - 世界空间中的上方向 + +**返回:** `Matrix4` - 视图矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 view = Matrix4::LookAt(cameraPos, target, Vector3::Up()); +``` diff --git a/docs/api/math/matrix4/matrix4.md b/docs/api/math/matrix4/matrix4.md new file mode 100644 index 0000000..c5e90c6 --- /dev/null +++ b/docs/api/math/matrix4/matrix4.md @@ -0,0 +1,79 @@ +# Matrix4 / Matrix4x4 + +4x4 矩阵结构体,用于表示完整的 3D 变换(平移、旋转、缩放)、视图和投影变换。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 类型别名 + +```cpp +using Matrix4 = Matrix4x4; +``` + +## 存储方式 + +行优先存储 (row-major): +``` +m[0][0] m[0][1] m[0][2] m[0][3] +m[1][0] m[1][1] m[1][2] m[1][3] +m[2][0] m[2][1] m[2][2] m[2][3] +m[3][0] m[3][1] m[3][2] m[3][3] +``` + +## 静态工厂方法 + +### 基础变换 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Identity()](identity.md) | `Matrix4` | 单位矩阵 | +| [Zero()](zero.md) | `Matrix4` | 零矩阵 | +| [Translation(v)](translation.md) | `Matrix4` | 平移矩阵 | +| [Scale(v)](scale.md) | `Matrix4` | 缩放矩阵 | +| [Rotation(q)](rotation.md) | `Matrix4` | 旋转矩阵(四元数) | +| [TRS(translation, rotation, scale)](trs.md) | `Matrix4` | 完整变换 | + +### 旋转 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [RotationX(radians)](rotationx.md) | `Matrix4` | X 轴旋转 | +| [RotationY(radians)](rotationy.md) | `Matrix4` | Y 轴旋转 | +| [RotationZ(radians)](rotationz.md) | `Matrix4` | Z 轴旋转 | + +### 相机变换 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [LookAt(eye, target, up)](lookat.md) | `Matrix4` | 视图矩阵 | +| [Perspective(fov, aspect, near, far)](perspective.md) | `Matrix4` | 透视投影 | +| [Orthographic(left, right, bottom, top, near, far)](orthographic.md) | `Matrix4` | 正交投影 | + +## 实例方法 + +### 乘法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| `operator*(Matrix4, Matrix4)` | `Matrix4` | 矩阵乘法 | +| `operator*(Matrix4, Vector4)` | `Vector4` | 矩阵-向量乘法 | +| [MultiplyPoint(v)](multiplypoint.md) | `Vector3` | 点变换(带平移) | +| [MultiplyVector(v)](multiplyvector.md) | `Vector3` | 方向变换(不带平移) | + +### 分解 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Transpose()](transpose.md) | `Matrix4` | 转置矩阵 | +| [Inverse()](inverse.md) | `Matrix4` | 逆矩阵 | +| [Determinant()](determinant.md) | `float` | 行列式 | +| [GetTranslation()](gettranslation.md) | `Vector3` | 获取平移分量 | +| [GetRotation()](getrotation.md) | `Quaternion` | 获取旋转分量 | +| [GetScale()](getscale.md) | `Vector3` | 获取缩放分量 | +| [Decompose(translation, rotation, scale)](decompose.md) | `void` | 分解所有分量 | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/matrix4/multiplypoint.md b/docs/api/math/matrix4/multiplypoint.md new file mode 100644 index 0000000..059f1c9 --- /dev/null +++ b/docs/api/math/matrix4/multiplypoint.md @@ -0,0 +1,21 @@ +# Matrix4::MultiplyPoint + +```cpp +Vector3 MultiplyPoint(const Vector3& v) const +``` + +使用矩阵变换点(包含平移)。 + +**参数:** +- `v` - 要变换的点 + +**返回:** `Vector3` - 变换后的点 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 model = Matrix4::TRS(pos, rot, scale); +Vector3 worldPos = model.MultiplyPoint(localPos); +``` diff --git a/docs/api/math/matrix4/multiplyvector.md b/docs/api/math/matrix4/multiplyvector.md new file mode 100644 index 0000000..a0fa4f5 --- /dev/null +++ b/docs/api/math/matrix4/multiplyvector.md @@ -0,0 +1,21 @@ +# Matrix4::MultiplyVector + +```cpp +Vector3 MultiplyVector(const Vector3& v) const +``` + +使用矩阵变换方向向量(不包含平移)。 + +**参数:** +- `v` - 要变换的方向向量 + +**返回:** `Vector3` - 变换后的方向 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 model = Matrix4::TRS(pos, rot, scale); +Vector3 worldDir = model.MultiplyVector(localDir); +``` diff --git a/docs/api/math/matrix4/orthographic.md b/docs/api/math/matrix4/orthographic.md new file mode 100644 index 0000000..f8b156a --- /dev/null +++ b/docs/api/math/matrix4/orthographic.md @@ -0,0 +1,25 @@ +# Matrix4::Orthographic + +```cpp +static Matrix4 Orthographic(float left, float right, float bottom, float top, float near, float far) +``` + +创建正交投影矩阵。 + +**参数:** +- `left` - 左裁剪面 +- `right` - 右裁剪面 +- `bottom` - 下裁剪面 +- `top` - 上裁剪面 +- `near` - 近裁剪面距离 +- `far` - 远裁剪面距离 + +**返回:** `Matrix4` - 正交投影矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 ortho = Matrix4::Orthographic(-aspect, aspect, -1.0f, 1.0f, 0.1f, 100.0f); +``` diff --git a/docs/api/math/matrix4/perspective.md b/docs/api/math/matrix4/perspective.md new file mode 100644 index 0000000..8316a8c --- /dev/null +++ b/docs/api/math/matrix4/perspective.md @@ -0,0 +1,23 @@ +# Matrix4::Perspective + +```cpp +static Matrix4 Perspective(float fov, float aspect, float near, float far) +``` + +创建透视投影矩阵。 + +**参数:** +- `fov` - 垂直视野角度(弧度) +- `aspect` - 宽高比 +- `near` - 近裁剪面距离 +- `far` - 远裁剪面距离 + +**返回:** `Matrix4` - 透视投影矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 proj = Matrix4::Perspective(45.0f * DEG_TO_RAD, aspect, 0.1f, 100.0f); +``` diff --git a/docs/api/math/matrix4/rotation.md b/docs/api/math/matrix4/rotation.md new file mode 100644 index 0000000..b0b0b7b --- /dev/null +++ b/docs/api/math/matrix4/rotation.md @@ -0,0 +1,21 @@ +# Matrix4::Rotation + +```cpp +static Matrix4 Rotation(const Quaternion& q) +``` + +从四元数创建旋转矩阵。 + +**参数:** +- `q` - 四元数 + +**返回:** `Matrix4` - 旋转矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Quaternion rot = Quaternion::FromEulerAngles(0.0f, 90.0f * DEG_TO_RAD, 0.0f); +Matrix4 rotation = Matrix4::Rotation(rot); +``` diff --git a/docs/api/math/matrix4/rotationx.md b/docs/api/math/matrix4/rotationx.md new file mode 100644 index 0000000..1cf1fc7 --- /dev/null +++ b/docs/api/math/matrix4/rotationx.md @@ -0,0 +1,20 @@ +# Matrix4::RotationX + +```cpp +static Matrix4 RotationX(float radians) +``` + +创建绕 X 轴旋转的矩阵。 + +**参数:** +- `radians` - 旋转角度(弧度) + +**返回:** `Matrix4` - 旋转矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 rotX = Matrix4::RotationX(Math::HALF_PI); +``` diff --git a/docs/api/math/matrix4/rotationy.md b/docs/api/math/matrix4/rotationy.md new file mode 100644 index 0000000..039c703 --- /dev/null +++ b/docs/api/math/matrix4/rotationy.md @@ -0,0 +1,20 @@ +# Matrix4::RotationY + +```cpp +static Matrix4 RotationY(float radians) +``` + +创建绕 Y 轴旋转的矩阵。 + +**参数:** +- `radians` - 旋转角度(弧度) + +**返回:** `Matrix4` - 旋转矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 rotY = Matrix4::RotationY(Math::HALF_PI); +``` diff --git a/docs/api/math/matrix4/rotationz.md b/docs/api/math/matrix4/rotationz.md new file mode 100644 index 0000000..6774836 --- /dev/null +++ b/docs/api/math/matrix4/rotationz.md @@ -0,0 +1,20 @@ +# Matrix4::RotationZ + +```cpp +static Matrix4 RotationZ(float radians) +``` + +创建绕 Z 轴旋转的矩阵。 + +**参数:** +- `radians` - 旋转角度(弧度) + +**返回:** `Matrix4` - 旋转矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 rotZ = Matrix4::RotationZ(Math::HALF_PI); +``` diff --git a/docs/api/math/matrix4/scale.md b/docs/api/math/matrix4/scale.md new file mode 100644 index 0000000..8047760 --- /dev/null +++ b/docs/api/math/matrix4/scale.md @@ -0,0 +1,20 @@ +# Matrix4::Scale + +```cpp +static Matrix4 Scale(const Vector3& v) +``` + +创建缩放矩阵。 + +**参数:** +- `v` - 各轴缩放因子 + +**返回:** `Matrix4` - 缩放矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 scale = Matrix4::Scale(Vector3(2.0f, 2.0f, 2.0f)); +``` diff --git a/docs/api/math/matrix4/translation.md b/docs/api/math/matrix4/translation.md new file mode 100644 index 0000000..8b8b3ed --- /dev/null +++ b/docs/api/math/matrix4/translation.md @@ -0,0 +1,20 @@ +# Matrix4::Translation + +```cpp +static Matrix4 Translation(const Vector3& v) +``` + +创建平移矩阵。 + +**参数:** +- `v` - 平移向量 + +**返回:** `Matrix4` - 平移矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 translation = Matrix4::Translation(Vector3(1.0f, 2.0f, 3.0f)); +``` diff --git a/docs/api/math/matrix4/transpose.md b/docs/api/math/matrix4/transpose.md new file mode 100644 index 0000000..ad49034 --- /dev/null +++ b/docs/api/math/matrix4/transpose.md @@ -0,0 +1,18 @@ +# Matrix4::Transpose + +```cpp +Matrix4 Transpose() const +``` + +返回矩阵的转置。 + +**返回:** `Matrix4` - 转置矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 m = ...; +Matrix4 transposed = m.Transpose(); +``` diff --git a/docs/api/math/matrix4/trs.md b/docs/api/math/matrix4/trs.md new file mode 100644 index 0000000..3d0a334 --- /dev/null +++ b/docs/api/math/matrix4/trs.md @@ -0,0 +1,22 @@ +# Matrix4::TRS + +```cpp +static Matrix4 TRS(const Vector3& translation, const Quaternion& rotation, const Vector3& scale) +``` + +创建完整的 TRS(平移、旋转、缩放)变换矩阵。 + +**参数:** +- `translation` - 平移向量 +- `rotation` - 旋转四元数 +- `scale` - 缩放向量 + +**返回:** `Matrix4` - 组合变换矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 transform = Matrix4::TRS(position, rotation, Vector3::One()); +``` diff --git a/docs/api/math/matrix4/zero.md b/docs/api/math/matrix4/zero.md new file mode 100644 index 0000000..133c16d --- /dev/null +++ b/docs/api/math/matrix4/zero.md @@ -0,0 +1,17 @@ +# Matrix4::Zero + +```cpp +static Matrix4 Zero() +``` + +返回零矩阵。 + +**返回:** `Matrix4` - 零矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 zero = Matrix4::Zero(); +``` diff --git a/docs/api/math/plane/frompoints.md b/docs/api/math/plane/frompoints.md new file mode 100644 index 0000000..a9503a6 --- /dev/null +++ b/docs/api/math/plane/frompoints.md @@ -0,0 +1,22 @@ +# Plane::FromPoints + +```cpp +static Plane FromPoints(const Vector3& a, const Vector3& b, const Vector3& c) +``` + +从三个不共线点创建平面。 + +**参数:** +- `a` - 第一个点 +- `b` - 第二个点 +- `c` - 第三个点 + +**返回:** `Plane` - 由三点定义的平面 + +**复杂度:** O(1) + +**示例:** + +```cpp +Plane plane = Plane::FromPoints(p0, p1, p2); +``` diff --git a/docs/api/math/plane/getclosestpoint.md b/docs/api/math/plane/getclosestpoint.md new file mode 100644 index 0000000..17dfcc2 --- /dev/null +++ b/docs/api/math/plane/getclosestpoint.md @@ -0,0 +1,20 @@ +# Plane::GetClosestPoint + +```cpp +Vector3 GetClosestPoint(const Vector3& point) const +``` + +计算平面上最接近给定点的点。 + +**参数:** +- `point` - 参考点 + +**返回:** `Vector3` - 平面上最接近的点 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 closest = plane.GetClosestPoint(point); +``` diff --git a/docs/api/math/plane/getdistancetopoint.md b/docs/api/math/plane/getdistancetopoint.md new file mode 100644 index 0000000..6e79723 --- /dev/null +++ b/docs/api/math/plane/getdistancetopoint.md @@ -0,0 +1,20 @@ +# Plane::GetDistanceToPoint + +```cpp +float GetDistanceToPoint(const Vector3& point) const +``` + +计算点到平面的有符号距离。 + +**参数:** +- `point` - 要计算的点 + +**返回:** `float` - 有符号距离 + +**复杂度:** O(1) + +**示例:** + +```cpp +float dist = plane.GetDistanceToPoint(point); +``` diff --git a/docs/api/math/plane/getside.md b/docs/api/math/plane/getside.md new file mode 100644 index 0000000..b694852 --- /dev/null +++ b/docs/api/math/plane/getside.md @@ -0,0 +1,20 @@ +# Plane::GetSide + +```cpp +bool GetSide(const Vector3& point) const +``` + +判断点在平面的哪一侧。 + +**参数:** +- `point` - 要测试的点 + +**返回:** `bool` - true 表示点在法线方向一侧 + +**复杂度:** O(1) + +**示例:** + +```cpp +if (plane.GetSide(point)) { /* point is on normal side */ } +``` diff --git a/docs/api/math/plane/intersects.md b/docs/api/math/plane/intersects.md new file mode 100644 index 0000000..03c8855 --- /dev/null +++ b/docs/api/math/plane/intersects.md @@ -0,0 +1,20 @@ +# Plane::Intersects + +```cpp +bool Intersects(const Sphere& sphere) const +``` + +检测平面是否与球体相交。 + +**参数:** +- `sphere` - 要检测的球体 + +**返回:** `bool` - true 表示相交 + +**复杂度:** O(1) + +**示例:** + +```cpp +if (plane.Intersects(sphere)) { /* collision */ } +``` diff --git a/docs/api/math/plane/plane.md b/docs/api/math/plane/plane.md new file mode 100644 index 0000000..8978232 --- /dev/null +++ b/docs/api/math/plane/plane.md @@ -0,0 +1,40 @@ +# Plane + +3D 平面结构体,由法线和距离表示。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 结构体定义 + +```cpp +struct Plane { + Vector3 normal = Vector3::Up(); + float distance = 0.0f; +}; +``` + +## 构造函数 + +- `Plane()` - 默认构造 (y=0 平面) +- `Plane(const Vector3& normal, float distance)` - 从法线和距离构造 + +## 静态工厂方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [FromPoints(a, b, c)](frompoints.md) | `Plane` | 从三个不共线点创建 | + +## 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [GetDistanceToPoint(point)](getdistancetopoint.md) | `float` | 点到平面的有符号距离 | +| [GetClosestPoint(point)](getclosestpoint.md) | `Vector3` | 平面上最接近给定点的点 | +| [GetSide(point)](getside.md) | `bool` | 点在平面的哪一侧 | +| [Intersects(sphere)](intersects.md) | `bool` | 与球体相交 | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/quaternion/dot.md b/docs/api/math/quaternion/dot.md new file mode 100644 index 0000000..8daf0d7 --- /dev/null +++ b/docs/api/math/quaternion/dot.md @@ -0,0 +1,20 @@ +# Quaternion::Dot + +```cpp +float Dot(const Quaternion& other) const +``` + +计算两个四元数的点积。 + +**参数:** +- `other` - 另一个四元数 + +**返回:** `float` - 点积结果 + +**复杂度:** O(1) + +**示例:** + +```cpp +float dot = quat1.Dot(quat2); +``` diff --git a/docs/api/math/quaternion/fromaxisangle.md b/docs/api/math/quaternion/fromaxisangle.md new file mode 100644 index 0000000..0db57df --- /dev/null +++ b/docs/api/math/quaternion/fromaxisangle.md @@ -0,0 +1,21 @@ +# Quaternion::FromAxisAngle + +```cpp +static Quaternion FromAxisAngle(const Vector3& axis, float radians) +``` + +从轴角创建四元数。 + +**参数:** +- `axis` - 旋转轴(应为单位向量) +- `radians` - 旋转角度(弧度) + +**返回:** `Quaternion` - 表示旋转的四元数 + +**复杂度:** O(1) + +**示例:** + +```cpp +Quaternion rot = Quaternion::FromAxisAngle(Vector3::Up(), 90.0f * DEG_TO_RAD); +``` diff --git a/docs/api/math/quaternion/fromeulerangles.md b/docs/api/math/quaternion/fromeulerangles.md new file mode 100644 index 0000000..b3d3c3b --- /dev/null +++ b/docs/api/math/quaternion/fromeulerangles.md @@ -0,0 +1,25 @@ +# Quaternion::FromEulerAngles + +```cpp +static Quaternion FromEulerAngles(float pitch, float yaw, float roll) +static Quaternion FromEulerAngles(const Vector3& euler) +``` + +从欧拉角创建四元数。角度以弧度为单位。 + +**参数:** +- `pitch` - 俯仰角(X 轴旋转) +- `yaw` - 偏航角(Y 轴旋转) +- `roll` - 翻滚角(Z 轴旋转) +- `euler` - 欧拉角向量 (pitch, yaw, roll) + +**返回:** `Quaternion` - 表示旋转的四元数 + +**复杂度:** O(1) + +**示例:** + +```cpp +Quaternion rot = Quaternion::FromEulerAngles(0.0f, 90.0f * DEG_TO_RAD, 0.0f); +Quaternion rot2 = Quaternion::FromEulerAngles(Vector3(0.0f, 90.0f * DEG_TO_RAD, 0.0f)); +``` diff --git a/docs/api/math/quaternion/fromrotationmatrix.md b/docs/api/math/quaternion/fromrotationmatrix.md new file mode 100644 index 0000000..82c45e5 --- /dev/null +++ b/docs/api/math/quaternion/fromrotationmatrix.md @@ -0,0 +1,21 @@ +# Quaternion::FromRotationMatrix + +```cpp +static Quaternion FromRotationMatrix(const Matrix4x4& matrix) +``` + +从旋转矩阵创建四元数。 + +**参数:** +- `matrix` - 旋转矩阵 + +**返回:** `Quaternion` - 表示相同旋转的四元数 + +**复杂度:** O(1) + +**示例:** + +```cpp +Matrix4 rotMat = Matrix4::RotationY(90.0f * DEG_TO_RAD); +Quaternion quat = Quaternion::FromRotationMatrix(rotMat); +``` diff --git a/docs/api/math/quaternion/identity.md b/docs/api/math/quaternion/identity.md new file mode 100644 index 0000000..965437a --- /dev/null +++ b/docs/api/math/quaternion/identity.md @@ -0,0 +1,17 @@ +# Quaternion::Identity + +```cpp +static Quaternion Identity() +``` + +返回恒等四元数(无旋转)。 + +**返回:** `Quaternion` - 值为 (0, 0, 0, 1) 的四元数 + +**复杂度:** O(1) + +**示例:** + +```cpp +Quaternion identity = Quaternion::Identity(); +``` diff --git a/docs/api/math/quaternion/inverse.md b/docs/api/math/quaternion/inverse.md new file mode 100644 index 0000000..a9e1aa9 --- /dev/null +++ b/docs/api/math/quaternion/inverse.md @@ -0,0 +1,17 @@ +# Quaternion::Inverse + +```cpp +Quaternion Inverse() const +``` + +返回四元数的逆(对于单位四元数就是共轭)。 + +**返回:** `Quaternion` - 逆四元数 + +**复杂度:** O(1) + +**示例:** + +```cpp +Quaternion inv = quat.Inverse(); +``` diff --git a/docs/api/math/quaternion/lookrotation.md b/docs/api/math/quaternion/lookrotation.md new file mode 100644 index 0000000..59de421 --- /dev/null +++ b/docs/api/math/quaternion/lookrotation.md @@ -0,0 +1,21 @@ +# Quaternion::LookRotation + +```cpp +static Quaternion LookRotation(const Vector3& forward, const Vector3& up = Vector3::Up()) +``` + +创建使 forward 方向朝向目标的旋转四元数。 + +**参数:** +- `forward` - 前方向向量 +- `up` - 上方向向量(默认 Y 轴向上) + +**返回:** `Quaternion` - 看向方向的旋转 + +**复杂度:** O(1) + +**示例:** + +```cpp +Quaternion lookAt = Quaternion::LookRotation(target - position); +``` diff --git a/docs/api/math/quaternion/magnitude.md b/docs/api/math/quaternion/magnitude.md new file mode 100644 index 0000000..a17b42b --- /dev/null +++ b/docs/api/math/quaternion/magnitude.md @@ -0,0 +1,17 @@ +# Quaternion::Magnitude + +```cpp +float Magnitude() const +``` + +计算四元数的模长。 + +**返回:** `float` - 四元数的模长 + +**复杂度:** O(1) + +**示例:** + +```cpp +float mag = quat.Magnitude(); +``` diff --git a/docs/api/math/quaternion/normalized.md b/docs/api/math/quaternion/normalized.md new file mode 100644 index 0000000..db4822b --- /dev/null +++ b/docs/api/math/quaternion/normalized.md @@ -0,0 +1,40 @@ +# Quaternion::Normalized / Normalize + +## 实例方法 + +```cpp +Quaternion Normalized() const +``` + +返回当前四元数的归一化副本(不修改原四元数)。 + +**返回:** `Quaternion` - 归一化后的四元数副本 + +**复杂度:** O(1) + +**示例:** + +```cpp +Quaternion unit = quat.Normalized(); // quat 保持不变 +``` + +## 静态方法 + +```cpp +static Quaternion Normalize(const Quaternion& q) +``` + +归一化四元数。 + +**参数:** +- `q` - 要归一化的四元数 + +**返回:** `Quaternion` - 归一化后的四元数 + +**复杂度:** O(1) + +**示例:** + +```cpp +Quaternion unit = Quaternion::Normalize(quat); +``` diff --git a/docs/api/math/quaternion/quaternion-multiply.md b/docs/api/math/quaternion/quaternion-multiply.md new file mode 100644 index 0000000..7dc4ebf --- /dev/null +++ b/docs/api/math/quaternion/quaternion-multiply.md @@ -0,0 +1,23 @@ +# Quaternion * Vector3 + +```cpp +Vector3 operator*(const Quaternion& q, const Vector3& v) +``` + +用四元数旋转向量。 + +**参数:** +- `q` - 旋转四元数 +- `v` - 要旋转的向量 + +**返回:** `Vector3` - 旋转后的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Quaternion rot = Quaternion::FromEulerAngles(0.0f, 90.0f * DEG_TO_RAD, 0.0f); +Vector3 forward = Vector3::Forward(); +Vector3 rotated = rot * forward; +``` diff --git a/docs/api/math/quaternion/quaternion.md b/docs/api/math/quaternion/quaternion.md new file mode 100644 index 0000000..2b2fb1d --- /dev/null +++ b/docs/api/math/quaternion/quaternion.md @@ -0,0 +1,61 @@ +# Quaternion + +四元数结构体,用于表示 3D 旋转,避免欧拉角的万向锁问题。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 结构体定义 + +```cpp +struct Quaternion { + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; + float w = 1.0f; +}; +``` + +## 静态工厂方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Identity()](identity.md) | `Quaternion` | 返回 (0, 0, 0, 1),恒等旋转 | +| [FromAxisAngle(axis, radians)](fromaxisangle.md) | `Quaternion` | 从轴角创建 | +| [FromEulerAngles(pitch, yaw, roll)](fromeulerangles.md) | `Quaternion` | 从欧拉角创建(弧度) | +| [FromEulerAngles(euler)](fromeulerangles.md) | `Quaternion` | 从 Vector3 欧拉角创建 | +| [FromRotationMatrix(matrix)](fromrotationmatrix.md) | `Quaternion` | 从旋转矩阵创建 | +| [Slerp(a, b, t)](slerp.md) | `Quaternion` | 球面线性插值 | +| [LookRotation(forward, up)](lookrotation.md) | `Quaternion` | 看向方向 | + +## 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [ToEulerAngles()](toeulerangles.md) | `Vector3` | 转换为欧拉角(弧度) | +| [ToMatrix4x4()](tomatrix4x4.md) | `Matrix4` | 转换为 4x4 旋转矩阵 | +| [Inverse()](inverse.md) | `Quaternion` | 共轭/逆四元数 | +| [Dot(other)](dot.md) | `float` | 点积 | +| [Magnitude()](magnitude.md) | `float` | 模长 | +| [Normalized()](normalized.md) | `Quaternion` | 归一化副本 | + +## 静态方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Normalize(q)](normalized.md) | `Quaternion` | 归一化四元数 | + +## 运算符 + +| 运算符 | 描述 | +|--------|------| +| `operator*(Quaternion, Quaternion)` | 组合旋转 | + +## 与 Vector3 的乘法 + +[Vector3 * Quaternion](quaternion-multiply.md) - 用四元数旋转向量 + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/quaternion/slerp.md b/docs/api/math/quaternion/slerp.md new file mode 100644 index 0000000..a2e058f --- /dev/null +++ b/docs/api/math/quaternion/slerp.md @@ -0,0 +1,22 @@ +# Quaternion::Slerp + +```cpp +static Quaternion Slerp(const Quaternion& a, const Quaternion& b, float t) +``` + +在两个四元数之间进行球面线性插值。 + +**参数:** +- `a` - 起始四元数 +- `b` - 结束四元数 +- `t` - 插值因子(0-1) + +**返回:** `Quaternion` - 插值结果 + +**复杂度:** O(1) + +**示例:** + +```cpp +Quaternion lerped = Quaternion::Slerp(rot1, rot2, 0.5f); +``` diff --git a/docs/api/math/quaternion/toeulerangles.md b/docs/api/math/quaternion/toeulerangles.md new file mode 100644 index 0000000..13ba405 --- /dev/null +++ b/docs/api/math/quaternion/toeulerangles.md @@ -0,0 +1,18 @@ +# Quaternion::ToEulerAngles + +```cpp +Vector3 ToEulerAngles() const +``` + +将四元数转换为欧拉角(弧度)。 + +**返回:** `Vector3` - 欧拉角 (pitch, yaw, roll) + +**复杂度:** O(1) + +**示例:** + +```cpp +Quaternion rot = ...; +Vector3 euler = rot.ToEulerAngles(); +``` diff --git a/docs/api/math/quaternion/tomatrix4x4.md b/docs/api/math/quaternion/tomatrix4x4.md new file mode 100644 index 0000000..1e98b7f --- /dev/null +++ b/docs/api/math/quaternion/tomatrix4x4.md @@ -0,0 +1,18 @@ +# Quaternion::ToMatrix4x4 + +```cpp +Matrix4x4 ToMatrix4x4() const +``` + +将四元数转换为 4x4 旋转矩阵。 + +**返回:** `Matrix4x4` - 旋转矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Quaternion rot = ...; +Matrix4 mat = rot.ToMatrix4x4(); +``` diff --git a/docs/api/math/ray/getpoint.md b/docs/api/math/ray/getpoint.md new file mode 100644 index 0000000..5860f77 --- /dev/null +++ b/docs/api/math/ray/getpoint.md @@ -0,0 +1,22 @@ +# Ray::GetPoint + +```cpp +Vector3 GetPoint(float t) const +``` + +获取射线上指定距离处的点。 + +**参数:** +- `t` - 沿射线方向的参数距离 + +**返回:** `Vector3` - 射线上的点 `origin + direction * t` + +**复杂度:** O(1) + +**示例:** + +```cpp +Ray ray(cameraPosition, mouseRayDir.Normalized()); +float t = 100.0f; +Vector3 point = ray.GetPoint(t); // 沿射线方向 100 单位处的点 +``` diff --git a/docs/api/math/ray/intersects-box.md b/docs/api/math/ray/intersects-box.md new file mode 100644 index 0000000..9a7fb9c --- /dev/null +++ b/docs/api/math/ray/intersects-box.md @@ -0,0 +1,27 @@ +# Ray::Intersects (box) + +```cpp +bool Intersects(const Box& box, float& t) const +``` + +检测射线是否与 OBB(有向包围盒)相交。 + +**参数:** +- `box` - 要检测的 OBB 盒体 +- `t` - 输出交点的参数距离 + +**返回:** `bool` - 相交返回 true,否则返回 false + +**复杂度:** O(1) + +**示例:** + +```cpp +Ray ray(cameraPosition, rayDirection); +Box colliderBox = object.GetWorldBox(); +float t; +if (ray.Intersects(colliderBox, t)) { + Vector3 hitPoint = ray.GetPoint(t); + // 处理命中 +} +``` diff --git a/docs/api/math/ray/intersects-plane.md b/docs/api/math/ray/intersects-plane.md new file mode 100644 index 0000000..9a2a91e --- /dev/null +++ b/docs/api/math/ray/intersects-plane.md @@ -0,0 +1,27 @@ +# Ray::Intersects (plane) + +```cpp +bool Intersects(const Plane& plane, float& t) const +``` + +检测射线是否与平面相交。 + +**参数:** +- `plane` - 要检测的平面 +- `t` - 输出交点的参数距离 + +**返回:** `bool` - 相交返回 true(射线朝向平面),否则返回 false + +**复杂度:** O(1) + +**示例:** + +```cpp +Ray ray(cameraPosition, rayDirection); +Plane groundPlane = Plane::FromNormalAndPoint(Vector3::Up(), Vector3::Zero()); +float t; +if (ray.Intersects(groundPlane, t)) { + Vector3 hitPoint = ray.GetPoint(t); + // 射线命中地面 +} +``` diff --git a/docs/api/math/ray/intersects-sphere.md b/docs/api/math/ray/intersects-sphere.md new file mode 100644 index 0000000..400624c --- /dev/null +++ b/docs/api/math/ray/intersects-sphere.md @@ -0,0 +1,26 @@ +# Ray::Intersects (sphere) + +```cpp +bool Intersects(const Sphere& sphere, float& t) const +``` + +检测射线是否与球体相交。 + +**参数:** +- `sphere` - 要检测的球体 +- `t` - 输出最近交点的参数距离 + +**返回:** `bool` - 相交返回 true,否则返回 false + +**复杂度:** O(1) + +**示例:** + +```cpp +Ray ray(cameraPosition, rayDirection); +float t; +if (ray.Intersects(sphere, t)) { + Vector3 hitPoint = ray.GetPoint(t); + // 处理命中 +} +``` diff --git a/docs/api/math/ray/ray.md b/docs/api/math/ray/ray.md new file mode 100644 index 0000000..969d10e --- /dev/null +++ b/docs/api/math/ray/ray.md @@ -0,0 +1,44 @@ +# Ray + +3D 射线结构体,用于光线投射和拾取。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 结构体定义 + +```cpp +struct Ray { + Vector3 origin; // 射线起点 + Vector3 direction; // 归一化方向 + + Ray() = default; + Ray(const Vector3& origin, const Vector3& direction); + + Vector3 GetPoint(float t) const; + bool Intersects(const Sphere& sphere, float& t) const; + bool Intersects(const Box& box, float& t) const; + bool Intersects(const Plane& plane, float& t) const; +}; +``` + +## 构造函数 + +| 方法 | 描述 | +|------|------| +| `Ray()` | 默认构造 | +| `Ray(origin, direction)` | 从起点和方向构造 | + +## 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [GetPoint(t)](getpoint.md) | `Vector3` | 获取射线上 t 距离处的点 | +| [Intersects(sphere, t)](intersects-sphere.md) | `bool` | 与球体相交,输出距离 t | +| [Intersects(box, t)](intersects-box.md) | `bool` | 与 OBB 相交,输出距离 t | +| [Intersects(plane, t)](intersects-plane.md) | `bool` | 与平面相交,输出距离 t | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/rect/contains-float.md b/docs/api/math/rect/contains-float.md new file mode 100644 index 0000000..f6e1488 --- /dev/null +++ b/docs/api/math/rect/contains-float.md @@ -0,0 +1,24 @@ +# Rect::Contains (float) + +```cpp +bool Contains(float px, float py) const +``` + +检测浮点坐标点是否在矩形内。 + +**参数:** +- `px` - 点的 x 坐标 +- `py` - 点的 y 坐标 + +**返回:** `bool` - 点在矩形内(包含边界)返回 true + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect screenRect(0.0f, 0.0f, 1920.0f, 1080.0f); +if (screenRect.Contains(mouseX, mouseY)) { + // 鼠标在屏幕矩形内 +} +``` diff --git a/docs/api/math/rect/contains-vector2.md b/docs/api/math/rect/contains-vector2.md new file mode 100644 index 0000000..6936789 --- /dev/null +++ b/docs/api/math/rect/contains-vector2.md @@ -0,0 +1,24 @@ +# Rect::Contains (Vector2) + +```cpp +bool Contains(const Vector2& point) const +``` + +检测 Vector2 点是否在矩形内。 + +**参数:** +- `point` - 要检测的二维点 + +**返回:** `bool` - 点在矩形内(包含边界)返回 true + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rect(0.0f, 0.0f, 100.0f, 100.0f); +Vector2 point(50.0f, 50.0f); +if (rect.Contains(point)) { + // 点在矩形内 +} +``` diff --git a/docs/api/math/rect/getbottom.md b/docs/api/math/rect/getbottom.md new file mode 100644 index 0000000..090fe94 --- /dev/null +++ b/docs/api/math/rect/getbottom.md @@ -0,0 +1,18 @@ +# Rect::GetBottom + +```cpp +float GetBottom() const +``` + +获取矩形下边界。 + +**返回:** `float` - 下边界坐标 (y + height) + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rect(10.0f, 20.0f, 100.0f, 50.0f); +float bottom = rect.GetBottom(); // 70.0f +``` diff --git a/docs/api/math/rect/getcenter.md b/docs/api/math/rect/getcenter.md new file mode 100644 index 0000000..7c31bb5 --- /dev/null +++ b/docs/api/math/rect/getcenter.md @@ -0,0 +1,18 @@ +# Rect::GetCenter + +```cpp +Vector2 GetCenter() const +``` + +获取矩形中心点。 + +**返回:** `Vector2` - 中心点坐标 + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rect(10.0f, 20.0f, 100.0f, 50.0f); +Vector2 center = rect.GetCenter(); // (60.0f, 45.0f) +``` diff --git a/docs/api/math/rect/getleft.md b/docs/api/math/rect/getleft.md new file mode 100644 index 0000000..0c7ec2e --- /dev/null +++ b/docs/api/math/rect/getleft.md @@ -0,0 +1,18 @@ +# Rect::GetLeft + +```cpp +float GetLeft() const +``` + +获取矩形左边界。 + +**返回:** `float` - 左边界坐标 (x) + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rect(10.0f, 20.0f, 100.0f, 50.0f); +float left = rect.GetLeft(); // 10.0f +``` diff --git a/docs/api/math/rect/getposition.md b/docs/api/math/rect/getposition.md new file mode 100644 index 0000000..09fa66b --- /dev/null +++ b/docs/api/math/rect/getposition.md @@ -0,0 +1,18 @@ +# Rect::GetPosition + +```cpp +Vector2 GetPosition() const +``` + +获取矩形左上角位置。 + +**返回:** `Vector2` - 位置向量 (x, y) + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rect(10.0f, 20.0f, 100.0f, 50.0f); +Vector2 pos = rect.GetPosition(); // (10.0f, 20.0f) +``` diff --git a/docs/api/math/rect/getright.md b/docs/api/math/rect/getright.md new file mode 100644 index 0000000..f856094 --- /dev/null +++ b/docs/api/math/rect/getright.md @@ -0,0 +1,18 @@ +# Rect::GetRight + +```cpp +float GetRight() const +``` + +获取矩形右边界。 + +**返回:** `float` - 右边界坐标 (x + width) + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rect(10.0f, 20.0f, 100.0f, 50.0f); +float right = rect.GetRight(); // 110.0f +``` diff --git a/docs/api/math/rect/getsize.md b/docs/api/math/rect/getsize.md new file mode 100644 index 0000000..76ff522 --- /dev/null +++ b/docs/api/math/rect/getsize.md @@ -0,0 +1,18 @@ +# Rect::GetSize + +```cpp +Vector2 GetSize() const +``` + +获取矩形尺寸。 + +**返回:** `Vector2` - 尺寸向量 (width, height) + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rect(10.0f, 20.0f, 100.0f, 50.0f); +Vector2 size = rect.GetSize(); // (100.0f, 50.0f) +``` diff --git a/docs/api/math/rect/gettop.md b/docs/api/math/rect/gettop.md new file mode 100644 index 0000000..93a370f --- /dev/null +++ b/docs/api/math/rect/gettop.md @@ -0,0 +1,18 @@ +# Rect::GetTop + +```cpp +float GetTop() const +``` + +获取矩形上边界。 + +**返回:** `float` - 上边界坐标 (y) + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rect(10.0f, 20.0f, 100.0f, 50.0f); +float top = rect.GetTop(); // 20.0f +``` diff --git a/docs/api/math/rect/intersect.md b/docs/api/math/rect/intersect.md new file mode 100644 index 0000000..f3574fe --- /dev/null +++ b/docs/api/math/rect/intersect.md @@ -0,0 +1,23 @@ +# Rect::Intersect + +```cpp +static Rect Intersect(const Rect& a, const Rect& b) +``` + +计算两矩形的交集区域。 + +**参数:** +- `a` - 第一个矩形 +- `b` - 第二个矩形 + +**返回:** `Rect` - 两矩形的交集,若无交集则返回零尺寸矩形 + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rectA(0.0f, 0.0f, 100.0f, 100.0f); +Rect rectB(50.0f, 50.0f, 100.0f, 100.0f); +Rect overlap = Rect::Intersect(rectA, rectB); // (50, 50, 50, 50) +``` diff --git a/docs/api/math/rect/intersects.md b/docs/api/math/rect/intersects.md new file mode 100644 index 0000000..ffa5009 --- /dev/null +++ b/docs/api/math/rect/intersects.md @@ -0,0 +1,24 @@ +# Rect::Intersects + +```cpp +bool Intersects(const Rect& other) const +``` + +检测两矩形是否相交。 + +**参数:** +- `other` - 另一个矩形 + +**返回:** `bool` - 两矩形相交返回 true + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rectA(0.0f, 0.0f, 100.0f, 100.0f); +Rect rectB(50.0f, 50.0f, 100.0f, 100.0f); +if (rectA.Intersects(rectB)) { + // 两矩形相交 +} +``` diff --git a/docs/api/math/rect/rect-overview.md b/docs/api/math/rect/rect-overview.md new file mode 100644 index 0000000..9df7429 --- /dev/null +++ b/docs/api/math/rect/rect-overview.md @@ -0,0 +1,69 @@ +# Rect + +浮点矩形结构体,用于 2D 区域表示。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 结构体定义 + +```cpp +struct Rect { + float x = 0.0f; // 左边界 + float y = 0.0f; // 上边界 + float width = 0.0f; + float height = 0.0f; + + Rect() = default; + Rect(float x, float y, float w, float h) : x(x), y(y), width(w), height(h) {} +}; +``` + +## 构造函数 + +| 方法 | 描述 | +|------|------| +| `Rect()` | 默认构造,初始化为零 | +| `Rect(x, y, w, h)` | 从坐标和尺寸构造 | + +## 边界访问 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [GetLeft()](getleft.md) | `float` | 左边界 (x) | +| [GetRight()](getright.md) | `float` | 右边界 (x + width) | +| [GetTop()](gettop.md) | `float` | 上边界 (y) | +| [GetBottom()](getbottom.md) | `float` | 下边界 (y + height) | +| [GetPosition()](getposition.md) | `Vector2` | 左上角位置 (x, y) | +| [GetSize()](getsize.md) | `Vector2` | 尺寸 (width, height) | +| [GetCenter()](getcenter.md) | `Vector2` | 中心点 | + +## 检测方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Contains(px, py)](contains-float.md) | `bool` | 浮点坐标点检测 | +| [Contains(point)](contains-vector2.md) | `bool` | Vector2 点检测 | +| [Intersects(other)](intersects.md) | `bool` | 与另一矩形相交 | + +## 静态方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Intersect(a, b)](intersect.md) | `Rect` | 两矩形交集 | +| [Union(a, b)](union.md) | `Rect` | 两矩形并集 | + +## 设置方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Set(x, y, w, h)](set.md) | `void` | 设置所有值 | +| [SetPosition(x, y)](setposition-float.md) | `void` | 设置位置 | +| [SetPosition(position)](setposition-vector2.md) | `void` | 设置位置 | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Rect 模块总览 +- [RectInt](rectint.md) - 整数矩形版本 +- [Viewport](viewport.md) - 渲染视口 diff --git a/docs/api/math/rect/rect.md b/docs/api/math/rect/rect.md new file mode 100644 index 0000000..055eace --- /dev/null +++ b/docs/api/math/rect/rect.md @@ -0,0 +1,17 @@ +# Rect / RectInt / Viewport + +2D 矩形和视口结构体。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 目录 + +- [Rect](rect.md) - 浮点矩形 +- [RectInt](rectint.md) - 整数矩形 +- [Viewport](viewport.md) - 渲染视口 + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/rect/rectint-contains.md b/docs/api/math/rect/rectint-contains.md new file mode 100644 index 0000000..1c01382 --- /dev/null +++ b/docs/api/math/rect/rectint-contains.md @@ -0,0 +1,24 @@ +# RectInt::Contains + +```cpp +bool Contains(int32_t px, int32_t py) const +``` + +检测整数坐标点是否在矩形内。 + +**参数:** +- `px` - 点的 x 坐标 +- `py` - 点的 y 坐标 + +**返回:** `bool` - 点在矩形内(包含边界)返回 true + +**复杂度:** O(1) + +**示例:** + +```cpp +RectInt rect(0, 0, 1920, 1080); +if (rect.Contains(pixelX, pixelY)) { + // 像素在矩形内 +} +``` diff --git a/docs/api/math/rect/rectint-getbottom.md b/docs/api/math/rect/rectint-getbottom.md new file mode 100644 index 0000000..a9d9c9b --- /dev/null +++ b/docs/api/math/rect/rectint-getbottom.md @@ -0,0 +1,18 @@ +# RectInt::GetBottom + +```cpp +int32_t GetBottom() const +``` + +获取矩形下边界。 + +**返回:** `int32_t` - 下边界坐标 (y + height) + +**复杂度:** O(1) + +**示例:** + +```cpp +RectInt rect(10, 20, 100, 50); +int32_t bottom = rect.GetBottom(); // 70 +``` diff --git a/docs/api/math/rect/rectint-getcenter.md b/docs/api/math/rect/rectint-getcenter.md new file mode 100644 index 0000000..1cf06d5 --- /dev/null +++ b/docs/api/math/rect/rectint-getcenter.md @@ -0,0 +1,18 @@ +# RectInt::GetCenter + +```cpp +Vector2 GetCenter() const +``` + +获取矩形中心点(转换为浮点)。 + +**返回:** `Vector2` - 中心点坐标 + +**复杂度:** O(1) + +**示例:** + +```cpp +RectInt rect(10, 20, 100, 50); +Vector2 center = rect.GetCenter(); // (60.0f, 45.0f) +``` diff --git a/docs/api/math/rect/rectint-getleft.md b/docs/api/math/rect/rectint-getleft.md new file mode 100644 index 0000000..b83ec9f --- /dev/null +++ b/docs/api/math/rect/rectint-getleft.md @@ -0,0 +1,18 @@ +# RectInt::GetLeft + +```cpp +int32_t GetLeft() const +``` + +获取矩形左边界。 + +**返回:** `int32_t` - 左边界坐标 (x) + +**复杂度:** O(1) + +**示例:** + +```cpp +RectInt rect(10, 20, 100, 50); +int32_t left = rect.GetLeft(); // 10 +``` diff --git a/docs/api/math/rect/rectint-getposition.md b/docs/api/math/rect/rectint-getposition.md new file mode 100644 index 0000000..a409497 --- /dev/null +++ b/docs/api/math/rect/rectint-getposition.md @@ -0,0 +1,18 @@ +# RectInt::GetPosition + +```cpp +Vector2 GetPosition() const +``` + +获取矩形左上角位置(转换为浮点)。 + +**返回:** `Vector2` - 位置向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +RectInt rect(10, 20, 100, 50); +Vector2 pos = rect.GetPosition(); // (10.0f, 20.0f) +``` diff --git a/docs/api/math/rect/rectint-getright.md b/docs/api/math/rect/rectint-getright.md new file mode 100644 index 0000000..390ea84 --- /dev/null +++ b/docs/api/math/rect/rectint-getright.md @@ -0,0 +1,18 @@ +# RectInt::GetRight + +```cpp +int32_t GetRight() const +``` + +获取矩形右边界。 + +**返回:** `int32_t` - 右边界坐标 (x + width) + +**复杂度:** O(1) + +**示例:** + +```cpp +RectInt rect(10, 20, 100, 50); +int32_t right = rect.GetRight(); // 110 +``` diff --git a/docs/api/math/rect/rectint-getsize.md b/docs/api/math/rect/rectint-getsize.md new file mode 100644 index 0000000..f372cb7 --- /dev/null +++ b/docs/api/math/rect/rectint-getsize.md @@ -0,0 +1,18 @@ +# RectInt::GetSize + +```cpp +Vector2 GetSize() const +``` + +获取矩形尺寸(转换为浮点)。 + +**返回:** `Vector2` - 尺寸向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +RectInt rect(10, 20, 100, 50); +Vector2 size = rect.GetSize(); // (100.0f, 50.0f) +``` diff --git a/docs/api/math/rect/rectint-gettop.md b/docs/api/math/rect/rectint-gettop.md new file mode 100644 index 0000000..f25dec8 --- /dev/null +++ b/docs/api/math/rect/rectint-gettop.md @@ -0,0 +1,18 @@ +# RectInt::GetTop + +```cpp +int32_t GetTop() const +``` + +获取矩形上边界。 + +**返回:** `int32_t` - 上边界坐标 (y) + +**复杂度:** O(1) + +**示例:** + +```cpp +RectInt rect(10, 20, 100, 50); +int32_t top = rect.GetTop(); // 20 +``` diff --git a/docs/api/math/rect/rectint-intersects.md b/docs/api/math/rect/rectint-intersects.md new file mode 100644 index 0000000..dc57b5c --- /dev/null +++ b/docs/api/math/rect/rectint-intersects.md @@ -0,0 +1,24 @@ +# RectInt::Intersects + +```cpp +bool Intersects(const RectInt& other) const +``` + +检测两整数矩形是否相交。 + +**参数:** +- `other` - 另一个整数矩形 + +**返回:** `bool` - 两矩形相交返回 true + +**复杂度:** O(1) + +**示例:** + +```cpp +RectInt rectA(0, 0, 100, 100); +RectInt rectB(50, 50, 100, 100); +if (rectA.Intersects(rectB)) { + // 两矩形相交 +} +``` diff --git a/docs/api/math/rect/rectint.md b/docs/api/math/rect/rectint.md new file mode 100644 index 0000000..dda9548 --- /dev/null +++ b/docs/api/math/rect/rectint.md @@ -0,0 +1,53 @@ +# RectInt + +整数矩形结构体,用于像素级 2D 区域表示。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 结构体定义 + +```cpp +struct RectInt { + int32_t x = 0; + int32_t y = 0; + int32_t width = 0; + int32_t height = 0; + + RectInt() = default; + RectInt(int32_t x, int32_t y, int32_t w, int32_t h); +}; +``` + +## 构造函数 + +| 方法 | 描述 | +|------|------| +| `RectInt()` | 默认构造 | +| `RectInt(x, y, w, h)` | 从整数坐标和尺寸构造 | + +## 边界访问 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [GetLeft()](rectint-getleft.md) | `int32_t` | 左边界 | +| [GetRight()](rectint-getright.md) | `int32_t` | 右边界 | +| [GetTop()](rectint-gettop.md) | `int32_t` | 上边界 | +| [GetBottom()](rectint-getbottom.md) | `int32_t` | 下边界 | +| [GetPosition()](rectint-getposition.md) | `Vector2` | 位置(转换为浮点) | +| [GetSize()](rectint-getsize.md) | `Vector2` | 尺寸(转换为浮点) | +| [GetCenter()](rectint-getcenter.md) | `Vector2` | 中心点 | + +## 检测方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Contains(px, py)](rectint-contains.md) | `bool` | 整数坐标点检测 | +| [Intersects(other)](rectint-intersects.md) | `bool` | 与另一矩形相交 | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Rect 模块总览 +- [Rect](rect-overview.md) - 浮点矩形版本 +- [Viewport](viewport.md) - 渲染视口 diff --git a/docs/api/math/rect/set.md b/docs/api/math/rect/set.md new file mode 100644 index 0000000..641000c --- /dev/null +++ b/docs/api/math/rect/set.md @@ -0,0 +1,24 @@ +# Rect::Set + +```cpp +void Set(float newX, float newY, float newWidth, float newHeight) +``` + +设置矩形所有属性。 + +**参数:** +- `newX` - 新的左边界 +- `newY` - 新的上边界 +- `newWidth` - 新的宽度 +- `newHeight` - 新的高度 + +**返回:** `void` + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rect; +rect.Set(10.0f, 20.0f, 100.0f, 50.0f); +``` diff --git a/docs/api/math/rect/setposition-float.md b/docs/api/math/rect/setposition-float.md new file mode 100644 index 0000000..51f9695 --- /dev/null +++ b/docs/api/math/rect/setposition-float.md @@ -0,0 +1,22 @@ +# Rect::SetPosition (float) + +```cpp +void SetPosition(float newX, float newY) +``` + +设置矩形位置(保持尺寸不变)。 + +**参数:** +- `newX` - 新的左边界 +- `newY` - 新的上边界 + +**返回:** `void` + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rect(0.0f, 0.0f, 100.0f, 50.0f); +rect.SetPosition(50.0f, 30.0f); // rect 现在为 (50, 30, 100, 50) +``` diff --git a/docs/api/math/rect/setposition-vector2.md b/docs/api/math/rect/setposition-vector2.md new file mode 100644 index 0000000..89f4020 --- /dev/null +++ b/docs/api/math/rect/setposition-vector2.md @@ -0,0 +1,21 @@ +# Rect::SetPosition (Vector2) + +```cpp +void SetPosition(const Vector2& position) +``` + +用 Vector2 设置矩形位置(保持尺寸不变)。 + +**参数:** +- `position` - 新的位置向量 + +**返回:** `void` + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rect(0.0f, 0.0f, 100.0f, 50.0f); +rect.SetPosition(Vector2(50.0f, 30.0f)); // rect 现在为 (50, 30, 100, 50) +``` diff --git a/docs/api/math/rect/union.md b/docs/api/math/rect/union.md new file mode 100644 index 0000000..acaca22 --- /dev/null +++ b/docs/api/math/rect/union.md @@ -0,0 +1,23 @@ +# Rect::Union + +```cpp +static Rect Union(const Rect& a, const Rect& b) +``` + +计算包含两矩形的最小矩形。 + +**参数:** +- `a` - 第一个矩形 +- `b` - 第二个矩形 + +**返回:** `Rect` - 包含两矩形的最小外接矩形 + +**复杂度:** O(1) + +**示例:** + +```cpp +Rect rectA(0.0f, 0.0f, 50.0f, 50.0f); +Rect rectB(100.0f, 100.0f, 50.0f, 50.0f); +Rect combined = Rect::Union(rectA, rectB); // (0, 0, 150, 150) +``` diff --git a/docs/api/math/rect/viewport-getaspectratio.md b/docs/api/math/rect/viewport-getaspectratio.md new file mode 100644 index 0000000..e1a9355 --- /dev/null +++ b/docs/api/math/rect/viewport-getaspectratio.md @@ -0,0 +1,18 @@ +# Viewport::GetAspectRatio + +```cpp +float GetAspectRatio() const +``` + +获取视口宽高比。 + +**返回:** `float` - 宽高比 (width / height),height 为 0 时返回 0.0f + +**复杂度:** O(1) + +**示例:** + +```cpp +Viewport viewport(0, 0, 1920, 1080); +float aspect = viewport.GetAspectRatio(); // 1.777... (16:9) +``` diff --git a/docs/api/math/rect/viewport-getrect.md b/docs/api/math/rect/viewport-getrect.md new file mode 100644 index 0000000..274b8be --- /dev/null +++ b/docs/api/math/rect/viewport-getrect.md @@ -0,0 +1,18 @@ +# Viewport::GetRect + +```cpp +Rect GetRect() const +``` + +将视口转换为 Rect。 + +**返回:** `Rect` - 对应的矩形 (x, y, width, height),不包含深度范围 + +**复杂度:** O(1) + +**示例:** + +```cpp +Viewport viewport(0, 0, 1920, 1080, 0.0f, 1.0f); +Rect rect = viewport.GetRect(); // (0, 0, 1920, 1080) +``` diff --git a/docs/api/math/rect/viewport.md b/docs/api/math/rect/viewport.md new file mode 100644 index 0000000..b3a45e0 --- /dev/null +++ b/docs/api/math/rect/viewport.md @@ -0,0 +1,45 @@ +# Viewport + +渲染视口结构体,用于屏幕到归一化坐标的映射。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 结构体定义 + +```cpp +struct Viewport { + float x = 0.0f; + float y = 0.0f; + float width = 0.0f; + float height = 0.0f; + float minDepth = 0.0f; + float maxDepth = 1.0f; + + Viewport() = default; + Viewport(float x, float y, float w, float h); + Viewport(float x, float y, float w, float h, float minD, float maxD); +}; +``` + +## 构造函数 + +| 方法 | 描述 | +|------|------| +| `Viewport()` | 默认构造 | +| `Viewport(x, y, w, h)` | 2D 视口 | +| `Viewport(x, y, w, h, minD, maxD)` | 带深度范围的 3D 视口 | + +## 方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [GetAspectRatio()](viewport-getaspectratio.md) | `float` | 宽高比 (width / height) | +| [GetRect()](viewport-getrect.md) | `Rect` | 转换为 Rect | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Rect 模块总览 +- [Rect](rect-overview.md) - 浮点矩形 +- [RectInt](rectint.md) - 整数矩形 diff --git a/docs/api/math/sphere/contains.md b/docs/api/math/sphere/contains.md new file mode 100644 index 0000000..6e69e32 --- /dev/null +++ b/docs/api/math/sphere/contains.md @@ -0,0 +1,20 @@ +# Sphere::Contains + +```cpp +bool Contains(const Vector3& point) const +``` + +检测点是否在球体内(包括表面)。 + +**参数:** +- `point` - 要检测的点 + +**返回:** `bool` - true 表示点在球体内 + +**复杂度:** O(1) + +**示例:** + +```cpp +if (sphere.Contains(point)) { /* point inside */ } +``` diff --git a/docs/api/math/sphere/intersects.md b/docs/api/math/sphere/intersects.md new file mode 100644 index 0000000..d3d5ad5 --- /dev/null +++ b/docs/api/math/sphere/intersects.md @@ -0,0 +1,20 @@ +# Sphere::Intersects + +```cpp +bool Intersects(const Sphere& other) const +``` + +检测两个球体是否相交。 + +**参数:** +- `other` - 另一个球体 + +**返回:** `bool` - true 表示相交 + +**复杂度:** O(1) + +**示例:** + +```cpp +if (sphere.Intersects(other)) { /* collision */ } +``` diff --git a/docs/api/math/sphere/sphere.md b/docs/api/math/sphere/sphere.md new file mode 100644 index 0000000..b0bd94c --- /dev/null +++ b/docs/api/math/sphere/sphere.md @@ -0,0 +1,32 @@ +# Sphere + +3D 球体结构体。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 结构体定义 + +```cpp +struct Sphere { + Vector3 center = Vector3::Zero(); + float radius = 0.0f; +}; +``` + +## 构造函数 + +- `Sphere()` - 默认构造 +- `Sphere(const Vector3& center, float radius)` - 从中心和半径构造 + +## 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Contains(point)](contains.md) | `bool` | 点是否在球体内 | +| [Intersects(other)](intersects.md) | `bool` | 与另一个球体相交 | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/transform/inverse.md b/docs/api/math/transform/inverse.md new file mode 100644 index 0000000..8b4de54 --- /dev/null +++ b/docs/api/math/transform/inverse.md @@ -0,0 +1,17 @@ +# Transform::Inverse + +```cpp +Transform Inverse() const +``` + +返回变换的逆。 + +**返回:** `Transform` - 逆变换 + +**复杂度:** O(1) + +**示例:** + +```cpp +Transform inv = transform.Inverse(); +``` diff --git a/docs/api/math/transform/inversetransformdirection.md b/docs/api/math/transform/inversetransformdirection.md new file mode 100644 index 0000000..38968c1 --- /dev/null +++ b/docs/api/math/transform/inversetransformdirection.md @@ -0,0 +1,21 @@ +# Transform::InverseTransformDirection + +```cpp +Vector3 InverseTransformDirection(const Vector3& direction) const +``` + +对方向进行逆变换(包含缩放处理)。 + +**参数:** +- `direction` - 世界空间中的方向 + +**返回:** `Vector3` - 局部空间中的方向 + +**复杂度:** O(1) + +**示例:** + +```cpp +Transform t; +Vector3 localDir = t.InverseTransformDirection(worldDir); +``` diff --git a/docs/api/math/transform/inversetransformpoint.md b/docs/api/math/transform/inversetransformpoint.md new file mode 100644 index 0000000..733b173 --- /dev/null +++ b/docs/api/math/transform/inversetransformpoint.md @@ -0,0 +1,21 @@ +# Transform::InverseTransformPoint + +```cpp +Vector3 InverseTransformPoint(const Vector3& point) const +``` + +对点进行逆变换。 + +**参数:** +- `point` - 世界空间中的点 + +**返回:** `Vector3` - 局部空间中的点 + +**复杂度:** O(1) + +**示例:** + +```cpp +Transform t; +Vector3 localPos = t.InverseTransformPoint(worldPos); +``` diff --git a/docs/api/math/transform/tomatrix.md b/docs/api/math/transform/tomatrix.md new file mode 100644 index 0000000..cfa9edd --- /dev/null +++ b/docs/api/math/transform/tomatrix.md @@ -0,0 +1,19 @@ +# Transform::ToMatrix + +```cpp +Matrix4 ToMatrix() const +``` + +将变换转换为 4x4 变换矩阵。 + +**返回:** `Matrix4` - TRS 变换矩阵 + +**复杂度:** O(1) + +**示例:** + +```cpp +Transform t; +t.position = Vector3(1.0f, 2.0f, 3.0f); +Matrix4 matrix = t.ToMatrix(); +``` diff --git a/docs/api/math/transform/transform.md b/docs/api/math/transform/transform.md new file mode 100644 index 0000000..ab3f9ff --- /dev/null +++ b/docs/api/math/transform/transform.md @@ -0,0 +1,39 @@ +# Transform + +3D 变换结构体,包含位置、旋转和缩放,用于层次化变换。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## Space 枚举 + +```cpp +enum class Space { Self, World }; +``` + +## 结构体定义 + +```cpp +struct Transform { + Vector3 position = Vector3::Zero(); + Quaternion rotation = Quaternion::Identity(); + Vector3 scale = Vector3::One(); +}; +``` + +## 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [ToMatrix()](tomatrix.md) | `Matrix4` | 转换为 4x4 变换矩阵 | +| [Inverse()](inverse.md) | `Transform` | 逆变换 | +| `operator*(Transform, Transform)` | `Transform` | 组合变换 | +| [TransformPoint(point)](transformpoint.md) | `Vector3` | 变换点(带平移) | +| [TransformDirection(direction)](transformdirection.md) | `Vector3` | 变换方向(包含旋转和缩放) | +| [InverseTransformPoint(point)](inversetransformpoint.md) | `Vector3` | 逆变换点 | +| [InverseTransformDirection(direction)](inversetransformdirection.md) | `Vector3` | 逆变换方向 | + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/transform/transformdirection.md b/docs/api/math/transform/transformdirection.md new file mode 100644 index 0000000..e371d00 --- /dev/null +++ b/docs/api/math/transform/transformdirection.md @@ -0,0 +1,22 @@ +# Transform::TransformDirection + +```cpp +Vector3 TransformDirection(const Vector3& direction) const +``` + +变换方向(仅旋转,包含缩放)。 + +**参数:** +- `direction` - 要变换的方向 + +**返回:** `Vector3` - 变换后的方向 + +**复杂度:** O(1) + +**示例:** + +```cpp +Transform t; +Vector3 localDir(1.0f, 0.0f, 0.0f); +Vector3 worldDir = t.TransformDirection(localDir); +``` diff --git a/docs/api/math/transform/transformpoint.md b/docs/api/math/transform/transformpoint.md new file mode 100644 index 0000000..46d9ec1 --- /dev/null +++ b/docs/api/math/transform/transformpoint.md @@ -0,0 +1,22 @@ +# Transform::TransformPoint + +```cpp +Vector3 TransformPoint(const Vector3& point) const +``` + +变换点(包含位置、旋转和缩放)。 + +**参数:** +- `point` - 要变换的点 + +**返回:** `Vector3` - 变换后的点 + +**复杂度:** O(1) + +**示例:** + +```cpp +Transform t; +Vector3 localPos(1.0f, 0.0f, 0.0f); +Vector3 worldPos = t.TransformPoint(localPos); +``` diff --git a/docs/api/math/vector2/cross.md b/docs/api/math/vector2/cross.md new file mode 100644 index 0000000..779916f --- /dev/null +++ b/docs/api/math/vector2/cross.md @@ -0,0 +1,23 @@ +# Vector2::Cross + +```cpp +static float Cross(const Vector2& a, const Vector2& b) +``` + +计算两个 2D 向量的叉积(返回标量)。结果为正值表示 b 在 a 的逆时针方向。 + +**参数:** +- `a` - 第一个向量 +- `b` - 第二个向量 + +**返回:** `float` - 叉积结果 a.x * b.y - a.y * b.x + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 a(1.0f, 0.0f); +Vector2 b(0.0f, 1.0f); +float cross = Vector2::Cross(a, b); // 1.0f (逆时针) +``` diff --git a/docs/api/math/vector2/dot.md b/docs/api/math/vector2/dot.md new file mode 100644 index 0000000..d2159f5 --- /dev/null +++ b/docs/api/math/vector2/dot.md @@ -0,0 +1,23 @@ +# Vector2::Dot + +```cpp +static float Dot(const Vector2& a, const Vector2& b) +``` + +计算两个 2D 向量的点积。 + +**参数:** +- `a` - 第一个向量 +- `b` - 第二个向量 + +**返回:** `float` - 点积结果 a.x * b.x + a.y * b.y + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 a(1.0f, 0.0f); +Vector2 b(0.0f, 1.0f); +float dot = Vector2::Dot(a, b); // 0.0f +``` diff --git a/docs/api/math/vector2/down.md b/docs/api/math/vector2/down.md new file mode 100644 index 0000000..3481b33 --- /dev/null +++ b/docs/api/math/vector2/down.md @@ -0,0 +1,17 @@ +# Vector2::Down + +```cpp +static Vector2 Down() +``` + +返回下方向向量 (0, -1)。 + +**返回:** `Vector2` - 值为 (0, -1) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 down = Vector2::Down(); +``` diff --git a/docs/api/math/vector2/left.md b/docs/api/math/vector2/left.md new file mode 100644 index 0000000..692d318 --- /dev/null +++ b/docs/api/math/vector2/left.md @@ -0,0 +1,17 @@ +# Vector2::Left + +```cpp +static Vector2 Left() +``` + +返回左方向向量 (-1, 0)。 + +**返回:** `Vector2` - 值为 (-1, 0) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 left = Vector2::Left(); +``` diff --git a/docs/api/math/vector2/lerp.md b/docs/api/math/vector2/lerp.md new file mode 100644 index 0000000..08c6651 --- /dev/null +++ b/docs/api/math/vector2/lerp.md @@ -0,0 +1,24 @@ +# Vector2::Lerp + +```cpp +static Vector2 Lerp(const Vector2& a, const Vector2& b, float t) +``` + +在线性插值两个向量之间。参数 t 会在 [0, 1] 范围内被限制。 + +**参数:** +- `a` - 起始向量 +- `b` - 结束向量 +- `t` - 插值因子,0 返回 a,1 返回 b + +**返回:** `Vector2` - 插值结果 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 start(0.0f, 0.0f); +Vector2 end(10.0f, 10.0f); +Vector2 mid = Vector2::Lerp(start, end, 0.5f); // (5.0f, 5.0f) +``` diff --git a/docs/api/math/vector2/magnitude.md b/docs/api/math/vector2/magnitude.md new file mode 100644 index 0000000..227d3d3 --- /dev/null +++ b/docs/api/math/vector2/magnitude.md @@ -0,0 +1,25 @@ +# Vector2::Magnitude + +```cpp +static float Magnitude(const Vector2& v) +float Magnitude() const +``` + +计算向量的长度(欧几里得范数)。 + +**静态版本参数:** +- `v` - 要计算长度的向量 + +**实例版本:** 计算当前向量的长度。 + +**返回:** `float` - 向量长度 sqrt(x * x + y * y) + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 v(3.0f, 4.0f); +float len = v.Magnitude(); // 5.0f +float len2 = Vector2::Magnitude(v); // 5.0f +``` diff --git a/docs/api/math/vector2/movetowards.md b/docs/api/math/vector2/movetowards.md new file mode 100644 index 0000000..db0f47a --- /dev/null +++ b/docs/api/math/vector2/movetowards.md @@ -0,0 +1,24 @@ +# Vector2::MoveTowards + +```cpp +static Vector2 MoveTowards(const Vector2& current, const Vector2& target, float maxDistance) +``` + +将当前向量朝目标向量移动指定距离。如果距离已小于 maxDistance,则直接返回目标。 + +**参数:** +- `current` - 当前向量 +- `target` - 目标向量 +- `maxDistance` - 最大移动距离 + +**返回:** `Vector2` - 移动后的位置 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 current(0.0f, 0.0f); +Vector2 target(10.0f, 0.0f); +Vector2 moved = Vector2::MoveTowards(current, target, 3.0f); // (3.0f, 0.0f) +``` diff --git a/docs/api/math/vector2/normalize.md b/docs/api/math/vector2/normalize.md new file mode 100644 index 0000000..3df54f1 --- /dev/null +++ b/docs/api/math/vector2/normalize.md @@ -0,0 +1,20 @@ +# Vector2::Normalize + +```cpp +static Vector2 Normalize(const Vector2& v) +``` + +将向量归一化为单位长度。如果向量长度接近零,返回零向量。 + +**参数:** +- `v` - 要归一化的向量 + +**返回:** `Vector2` - 归一化后的单位向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 dir = Vector2::Normalize(Vector2(3.0f, 4.0f)); // (0.6f, 0.8f) +``` diff --git a/docs/api/math/vector2/normalized.md b/docs/api/math/vector2/normalized.md new file mode 100644 index 0000000..1e62dac --- /dev/null +++ b/docs/api/math/vector2/normalized.md @@ -0,0 +1,18 @@ +# Vector2::Normalized + +```cpp +Vector2 Normalized() const +``` + +返回当前向量的归一化副本(单位长度)。不修改原向量。 + +**返回:** `Vector2` - 归一化后的向量副本 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 v(3.0f, 4.0f); +Vector2 unit = v.Normalized(); // (0.6f, 0.8f), v 保持不变 +``` diff --git a/docs/api/math/vector2/one.md b/docs/api/math/vector2/one.md new file mode 100644 index 0000000..bbce99f --- /dev/null +++ b/docs/api/math/vector2/one.md @@ -0,0 +1,17 @@ +# Vector2::One + +```cpp +static Vector2 One() +``` + +返回单位向量 (1, 1)。 + +**返回:** `Vector2` - 值为 (1, 1) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 unit = Vector2::One(); +``` diff --git a/docs/api/math/vector2/right.md b/docs/api/math/vector2/right.md new file mode 100644 index 0000000..89a8561 --- /dev/null +++ b/docs/api/math/vector2/right.md @@ -0,0 +1,17 @@ +# Vector2::Right + +```cpp +static Vector2 Right() +``` + +返回右方向向量 (1, 0)。 + +**返回:** `Vector2` - 值为 (1, 0) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 right = Vector2::Right(); +``` diff --git a/docs/api/math/vector2/sqrmagnitude.md b/docs/api/math/vector2/sqrmagnitude.md new file mode 100644 index 0000000..15183a2 --- /dev/null +++ b/docs/api/math/vector2/sqrmagnitude.md @@ -0,0 +1,25 @@ +# Vector2::SqrMagnitude + +```cpp +static float SqrMagnitude(const Vector2& v) +float SqrMagnitude() const +``` + +计算向量长度的平方。比 Magnitude 更快,避免了开方运算。 + +**静态版本参数:** +- `v` - 要计算长度的向量 + +**实例版本:** 计算当前向量的长度平方。 + +**返回:** `float` - 向量长度平方 x * x + y * y + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 v(3.0f, 4.0f); +float sqlen = v.SqrMagnitude(); // 25.0f +float sqlen2 = Vector2::SqrMagnitude(v); // 25.0f +``` diff --git a/docs/api/math/vector2/up.md b/docs/api/math/vector2/up.md new file mode 100644 index 0000000..bf7c697 --- /dev/null +++ b/docs/api/math/vector2/up.md @@ -0,0 +1,17 @@ +# Vector2::Up + +```cpp +static Vector2 Up() +``` + +返回上方向向量 (0, 1)。 + +**返回:** `Vector2` - 值为 (0, 1) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 up = Vector2::Up(); +``` diff --git a/docs/api/math/vector2/vector2.md b/docs/api/math/vector2/vector2.md new file mode 100644 index 0000000..95a904e --- /dev/null +++ b/docs/api/math/vector2/vector2.md @@ -0,0 +1,57 @@ +# Vector2 + +2D 向量结构体,用于表示 2D 空间中的点、方向或颜色。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 结构体定义 + +```cpp +struct Vector2 { + float x = 0.0f; + float y = 0.0f; +}; +``` + +## 静态工厂方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Zero()](zero.md) | `Vector2` | 返回 (0, 0) | +| [One()](one.md) | `Vector2` | 返回 (1, 1) | +| [Up()](up.md) | `Vector2` | 返回 (0, 1),上方向 | +| [Down()](down.md) | `Vector2` | 返回 (0, -1),下方向 | +| [Right()](right.md) | `Vector2` | 返回 (1, 0),右方向 | +| [Left()](left.md) | `Vector2` | 返回 (-1, 0),左方向 | + +## 静态数学方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Dot(a, b)](dot.md) | `float` | 点积 | +| [Cross(a, b)](cross.md) | `float` | 2D 叉积(返回标量) | +| [Normalize(v)](normalize.md) | `Vector2` | 归一化向量 | +| [Magnitude(v)](magnitude.md) | `float` | 向量长度 | +| [SqrMagnitude(v)](sqrmagnitude.md) | `float` | 长度平方(更快) | +| [Lerp(a, b, t)](lerp.md) | `Vector2` | 线性插值 | +| [MoveTowards(current, target, maxDistance)](movetowards.md) | `Vector2` | 朝目标移动 | + +## 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Magnitude()](magnitude.md) | `float` | 获取向量长度 | +| [SqrMagnitude()](sqrmagnitude.md) | `float` | 获取长度平方 | +| [Normalized()](normalized.md) | `Vector2` | 获取归一化副本 | + +## 运算符 + +- 算术: `+`, `-`, `*` (scalar), `/` (scalar) +- 复合赋值: `+=`, `-=`, `*=`, `/=` +- 比较: `==`, `!=` + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/vector2/zero.md b/docs/api/math/vector2/zero.md new file mode 100644 index 0000000..72c11cd --- /dev/null +++ b/docs/api/math/vector2/zero.md @@ -0,0 +1,17 @@ +# Vector2::Zero + +```cpp +static Vector2 Zero() +``` + +返回零向量 (0, 0)。 + +**返回:** `Vector2` - 值为 (0, 0) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector2 origin = Vector2::Zero(); +``` diff --git a/docs/api/math/vector3/angle.md b/docs/api/math/vector3/angle.md new file mode 100644 index 0000000..b6cc2f2 --- /dev/null +++ b/docs/api/math/vector3/angle.md @@ -0,0 +1,23 @@ +# Vector3::Angle + +```cpp +static float Angle(const Vector3& from, const Vector3& to) +``` + +计算两个向量之间的夹角(以度为单位)。 + +**参数:** +- `from` - 起始向量 +- `to` - 目标向量 + +**返回:** `float` - 两向量之间的夹角(0-180度) + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 a(1.0f, 0.0f, 0.0f); +Vector3 b(0.0f, 1.0f, 0.0f); +float angle = Vector3::Angle(a, b); // 90.0f +``` diff --git a/docs/api/math/vector3/back.md b/docs/api/math/vector3/back.md new file mode 100644 index 0000000..f630c31 --- /dev/null +++ b/docs/api/math/vector3/back.md @@ -0,0 +1,17 @@ +# Vector3::Back + +```cpp +static Vector3 Back() +``` + +返回后方向向量 (0, 0, -1)。 + +**返回:** `Vector3` - 值为 (0, 0, -1) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 back = Vector3::Back(); +``` diff --git a/docs/api/math/vector3/cross.md b/docs/api/math/vector3/cross.md new file mode 100644 index 0000000..b780267 --- /dev/null +++ b/docs/api/math/vector3/cross.md @@ -0,0 +1,23 @@ +# Vector3::Cross + +```cpp +static Vector3 Cross(const Vector3& a, const Vector3& b) +``` + +计算两个 3D 向量的叉积。结果向量同时垂直于 a 和 b。 + +**参数:** +- `a` - 第一个向量 +- `b` - 第二个向量 + +**返回:** `Vector3` - 叉积结果,垂直于 a 和 b 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 right(1.0f, 0.0f, 0.0f); +Vector3 up(0.0f, 1.0f, 0.0f); +Vector3 forward = Vector3::Cross(right, up); // (0, 0, 1) +``` diff --git a/docs/api/math/vector3/dot.md b/docs/api/math/vector3/dot.md new file mode 100644 index 0000000..91e0d8b --- /dev/null +++ b/docs/api/math/vector3/dot.md @@ -0,0 +1,23 @@ +# Vector3::Dot + +```cpp +static float Dot(const Vector3& a, const Vector3& b) +``` + +计算两个 3D 向量的点积。 + +**参数:** +- `a` - 第一个向量 +- `b` - 第二个向量 + +**返回:** `float` - 点积结果 a.x * b.x + a.y * b.y + a.z * b.z + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 a(1.0f, 0.0f, 0.0f); +Vector3 b(0.0f, 1.0f, 0.0f); +float dot = Vector3::Dot(a, b); // 0.0f +``` diff --git a/docs/api/math/vector3/down.md b/docs/api/math/vector3/down.md new file mode 100644 index 0000000..7b39dba --- /dev/null +++ b/docs/api/math/vector3/down.md @@ -0,0 +1,17 @@ +# Vector3::Down + +```cpp +static Vector3 Down() +``` + +返回下方向向量 (0, -1, 0)。 + +**返回:** `Vector3` - 值为 (0, -1, 0) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 down = Vector3::Down(); +``` diff --git a/docs/api/math/vector3/forward.md b/docs/api/math/vector3/forward.md new file mode 100644 index 0000000..ef19872 --- /dev/null +++ b/docs/api/math/vector3/forward.md @@ -0,0 +1,17 @@ +# Vector3::Forward + +```cpp +static Vector3 Forward() +``` + +返回前方向向量 (0, 0, 1)。 + +**返回:** `Vector3` - 值为 (0, 0, 1) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 forward = Vector3::Forward(); +``` diff --git a/docs/api/math/vector3/left.md b/docs/api/math/vector3/left.md new file mode 100644 index 0000000..b2f1173 --- /dev/null +++ b/docs/api/math/vector3/left.md @@ -0,0 +1,17 @@ +# Vector3::Left + +```cpp +static Vector3 Left() +``` + +返回左方向向量 (-1, 0, 0)。 + +**返回:** `Vector3` - 值为 (-1, 0, 0) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 left = Vector3::Left(); +``` diff --git a/docs/api/math/vector3/lerp.md b/docs/api/math/vector3/lerp.md new file mode 100644 index 0000000..dd59840 --- /dev/null +++ b/docs/api/math/vector3/lerp.md @@ -0,0 +1,24 @@ +# Vector3::Lerp + +```cpp +static Vector3 Lerp(const Vector3& a, const Vector3& b, float t) +``` + +在线性插值两个向量之间。参数 t 会在 [0, 1] 范围内被限制。 + +**参数:** +- `a` - 起始向量 +- `b` - 结束向量 +- `t` - 插值因子,0 返回 a,1 返回 b + +**返回:** `Vector3` - 插值结果 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 start(0.0f, 0.0f, 0.0f); +Vector3 end(10.0f, 10.0f, 10.0f); +Vector3 mid = Vector3::Lerp(start, end, 0.5f); // (5.0f, 5.0f, 5.0f) +``` diff --git a/docs/api/math/vector3/magnitude.md b/docs/api/math/vector3/magnitude.md new file mode 100644 index 0000000..c5c3e3f --- /dev/null +++ b/docs/api/math/vector3/magnitude.md @@ -0,0 +1,25 @@ +# Vector3::Magnitude + +```cpp +static float Magnitude(const Vector3& v) +float Magnitude() const +``` + +计算向量的长度(欧几里得范数)。 + +**静态版本参数:** +- `v` - 要计算长度的向量 + +**实例版本:** 计算当前向量的长度。 + +**返回:** `float` - 向量长度 sqrt(x * x + y * y + z * z) + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 v(1.0f, 2.0f, 2.0f); +float len = v.Magnitude(); // 3.0f +float len2 = Vector3::Magnitude(v); // 3.0f +``` diff --git a/docs/api/math/vector3/movetowards.md b/docs/api/math/vector3/movetowards.md new file mode 100644 index 0000000..e1d3992 --- /dev/null +++ b/docs/api/math/vector3/movetowards.md @@ -0,0 +1,24 @@ +# Vector3::MoveTowards + +```cpp +static Vector3 MoveTowards(const Vector3& current, const Vector3& target, float maxDistance) +``` + +将当前向量朝目标向量移动指定距离。如果距离已小于 maxDistance,则直接返回目标。 + +**参数:** +- `current` - 当前向量 +- `target` - 目标向量 +- `maxDistance` - 最大移动距离 + +**返回:** `Vector3` - 移动后的位置 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 current(0.0f, 0.0f, 0.0f); +Vector3 target(10.0f, 0.0f, 0.0f); +Vector3 moved = Vector3::MoveTowards(current, target, 3.0f); // (3.0f, 0, 0) +``` diff --git a/docs/api/math/vector3/normalize.md b/docs/api/math/vector3/normalize.md new file mode 100644 index 0000000..b35d436 --- /dev/null +++ b/docs/api/math/vector3/normalize.md @@ -0,0 +1,20 @@ +# Vector3::Normalize + +```cpp +static Vector3 Normalize(const Vector3& v) +``` + +将向量归一化为单位长度。如果向量长度接近零,返回零向量。 + +**参数:** +- `v` - 要归一化的向量 + +**返回:** `Vector3` - 归一化后的单位向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 dir = Vector3::Normalize(Vector3(3.0f, 4.0f, 0.0f)); // (0.6f, 0.8f, 0) +``` diff --git a/docs/api/math/vector3/normalized.md b/docs/api/math/vector3/normalized.md new file mode 100644 index 0000000..57f499d --- /dev/null +++ b/docs/api/math/vector3/normalized.md @@ -0,0 +1,18 @@ +# Vector3::Normalized + +```cpp +Vector3 Normalized() const +``` + +返回当前向量的归一化副本(单位长度)。不修改原向量。 + +**返回:** `Vector3` - 归一化后的向量副本 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 v(3.0f, 4.0f, 0.0f); +Vector3 unit = v.Normalized(); // (0.6f, 0.8f, 0), v 保持不变 +``` diff --git a/docs/api/math/vector3/one.md b/docs/api/math/vector3/one.md new file mode 100644 index 0000000..650c3d2 --- /dev/null +++ b/docs/api/math/vector3/one.md @@ -0,0 +1,17 @@ +# Vector3::One + +```cpp +static Vector3 One() +``` + +返回单位向量 (1, 1, 1)。 + +**返回:** `Vector3` - 值为 (1, 1, 1) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 unit = Vector3::One(); +``` diff --git a/docs/api/math/vector3/project.md b/docs/api/math/vector3/project.md new file mode 100644 index 0000000..dcff56c --- /dev/null +++ b/docs/api/math/vector3/project.md @@ -0,0 +1,23 @@ +# Vector3::Project + +```cpp +static Vector3 Project(const Vector3& vector, const Vector3& onNormal) +``` + +将向量投影到法线向量上。 + +**参数:** +- `vector` - 要投影的向量 +- `onNormal` - 投影到的法线向量 + +**返回:** `Vector3` - 投影结果。如果法线长度为 0,返回零向量。 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 v(1.0f, 1.0f, 0.0f); +Vector3 normal(1.0f, 0.0f, 0.0f); +Vector3 projected = Vector3::Project(v, normal); // (1, 0, 0) +``` diff --git a/docs/api/math/vector3/projectonplane.md b/docs/api/math/vector3/projectonplane.md new file mode 100644 index 0000000..84747f0 --- /dev/null +++ b/docs/api/math/vector3/projectonplane.md @@ -0,0 +1,23 @@ +# Vector3::ProjectOnPlane + +```cpp +static Vector3 ProjectOnPlane(const Vector3& vector, const Vector3& planeNormal) +``` + +将向量投影到平面上(减去沿平面法线的分量)。 + +**参数:** +- `vector` - 要投影的向量 +- `planeNormal` - 平面法线 + +**返回:** `Vector3` - 平面上的投影向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 v(1.0f, 1.0f, 1.0f); +Vector3 normal(0.0f, 1.0f, 0.0f); // XZ 平面 +Vector3 projected = Vector3::ProjectOnPlane(v, normal); // (1, 0, 1) +``` diff --git a/docs/api/math/vector3/quaternion-multiply.md b/docs/api/math/vector3/quaternion-multiply.md new file mode 100644 index 0000000..d21f0da --- /dev/null +++ b/docs/api/math/vector3/quaternion-multiply.md @@ -0,0 +1,23 @@ +# Vector3 * Quaternion + +```cpp +Vector3 operator*(const Quaternion& q, const Vector3& v) +``` + +用四元数旋转向量。 + +**参数:** +- `q` - 旋转四元数 +- `v` - 要旋转的向量 + +**返回:** `Vector3` - 旋转后的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Quaternion rot = Quaternion::FromEulerAngles(0.0f, 90.0f * DEG_TO_RAD, 0.0f); +Vector3 forward = Vector3::Forward(); +Vector3 rotated = rot * forward; // 绕 Y 轴旋转 90 度 +``` diff --git a/docs/api/math/vector3/reflect.md b/docs/api/math/vector3/reflect.md new file mode 100644 index 0000000..570be5f --- /dev/null +++ b/docs/api/math/vector3/reflect.md @@ -0,0 +1,23 @@ +# Vector3::Reflect + +```cpp +static Vector3 Reflect(const Vector3& inDirection, const Vector3& inNormal) +``` + +计算向量关于法线的反射方向。 + +**参数:** +- `inDirection` - 入射方向向量 +- `inNormal` - 反射表面的法线(应为单位向量) + +**返回:** `Vector3` - 反射方向 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 incoming(1.0f, -1.0f, 0.0f); +Vector3 normal(0.0f, 1.0f, 0.0f); +Vector3 reflected = Vector3::Reflect(incoming, normal); // (1, 1, 0) +``` diff --git a/docs/api/math/vector3/right.md b/docs/api/math/vector3/right.md new file mode 100644 index 0000000..7fe121b --- /dev/null +++ b/docs/api/math/vector3/right.md @@ -0,0 +1,17 @@ +# Vector3::Right + +```cpp +static Vector3 Right() +``` + +返回右方向向量 (1, 0, 0)。 + +**返回:** `Vector3` - 值为 (1, 0, 0) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 right = Vector3::Right(); +``` diff --git a/docs/api/math/vector3/sqrmagnitude.md b/docs/api/math/vector3/sqrmagnitude.md new file mode 100644 index 0000000..94e42d6 --- /dev/null +++ b/docs/api/math/vector3/sqrmagnitude.md @@ -0,0 +1,25 @@ +# Vector3::SqrMagnitude + +```cpp +static float SqrMagnitude(const Vector3& v) +float SqrMagnitude() const +``` + +计算向量长度的平方。比 Magnitude 更快,避免了开方运算。 + +**静态版本参数:** +- `v` - 要计算长度的向量 + +**实例版本:** 计算当前向量的长度平方。 + +**返回:** `float` - 向量长度平方 x * x + y * y + z * z + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 v(1.0f, 2.0f, 2.0f); +float sqlen = v.SqrMagnitude(); // 9.0f +float sqlen2 = Vector3::SqrMagnitude(v); // 9.0f +``` diff --git a/docs/api/math/vector3/up.md b/docs/api/math/vector3/up.md new file mode 100644 index 0000000..2ae2335 --- /dev/null +++ b/docs/api/math/vector3/up.md @@ -0,0 +1,17 @@ +# Vector3::Up + +```cpp +static Vector3 Up() +``` + +返回上方向向量 (0, 1, 0)。 + +**返回:** `Vector3` - 值为 (0, 1, 0) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 up = Vector3::Up(); +``` diff --git a/docs/api/math/vector3/vector3.md b/docs/api/math/vector3/vector3.md new file mode 100644 index 0000000..541a62b --- /dev/null +++ b/docs/api/math/vector3/vector3.md @@ -0,0 +1,69 @@ +# Vector3 + +3D 向量结构体,用于表示 3D 空间中的点、方向、颜色或法线。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 结构体定义 + +```cpp +struct Vector3 { + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; +}; +``` + +## 静态工厂方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Zero()](zero.md) | `Vector3` | 返回 (0, 0, 0) | +| [One()](one.md) | `Vector3` | 返回 (1, 1, 1) | +| [Forward()](forward.md) | `Vector3` | 返回 (0, 0, 1),前方向(Z+) | +| [Back()](back.md) | `Vector3` | 返回 (0, 0, -1),后方向 | +| [Up()](up.md) | `Vector3` | 返回 (0, 1, 0),上方向 | +| [Down()](down.md) | `Vector3` | 返回 (0, -1, 0),下方向 | +| [Right()](right.md) | `Vector3` | 返回 (1, 0, 0),右方向 | +| [Left()](left.md) | `Vector3` | 返回 (-1, 0, 0),左方向 | + +## 静态数学方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Dot(a, b)](dot.md) | `float` | 点积 | +| [Cross(a, b)](cross.md) | `Vector3` | 叉积(垂直于 a 和 b) | +| [Normalize(v)](normalize.md) | `Vector3` | 归一化向量 | +| [Magnitude(v)](magnitude.md) | `float` | 向量长度 | +| [SqrMagnitude(v)](sqrmagnitude.md) | `float` | 长度平方 | +| [Lerp(a, b, t)](lerp.md) | `Vector3` | 线性插值 | +| [MoveTowards(current, target, maxDistance)](movetowards.md) | `Vector3` | 朝目标移动 | +| [Project(vector, onNormal)](project.md) | `Vector3` | 投影到法线上 | +| [ProjectOnPlane(vector, planeNormal)](projectonplane.md) | `Vector3` | 投影到平面上 | +| [Angle(from, to)](angle.md) | `float` | 两向量夹角(度) | +| [Reflect(inDirection, inNormal)](reflect.md) | `Vector3` | 反射 | + +## 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Magnitude()](magnitude.md) | `float` | 获取向量长度 | +| [SqrMagnitude()](sqrmagnitude.md) | `float` | 获取长度平方 | +| [Normalized()](normalized.md) | `Vector3` | 获取归一化副本 | + +## 运算符 + +- 算术: `+`, `-`, `*` (scalar/memberwise), `/` (scalar/memberwise) +- 复合赋值: `+=`, `-=`, `*=`, `/=` +- 下标: `operator[]` (0=x, 1=y, 2=z) +- 比较: `==`, `!=` + +## 与 Quaternion 的乘法 + +[Vector3 * Quaternion](quaternion-multiply.md) - 用四元数旋转向量 + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/vector3/zero.md b/docs/api/math/vector3/zero.md new file mode 100644 index 0000000..2477012 --- /dev/null +++ b/docs/api/math/vector3/zero.md @@ -0,0 +1,17 @@ +# Vector3::Zero + +```cpp +static Vector3 Zero() +``` + +返回零向量 (0, 0, 0)。 + +**返回:** `Vector3` - 值为 (0, 0, 0) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector3 origin = Vector3::Zero(); +``` diff --git a/docs/api/math/vector4/dot.md b/docs/api/math/vector4/dot.md new file mode 100644 index 0000000..0e848f6 --- /dev/null +++ b/docs/api/math/vector4/dot.md @@ -0,0 +1,23 @@ +# Vector4::Dot + +```cpp +static float Dot(const Vector4& a, const Vector4& b) +``` + +计算两个 4D 向量的点积。 + +**参数:** +- `a` - 第一个向量 +- `b` - 第二个向量 + +**返回:** `float` - 点积结果 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector4 a(1.0f, 2.0f, 3.0f, 4.0f); +Vector4 b(4.0f, 3.0f, 2.0f, 1.0f); +float dot = Vector4::Dot(a, b); // 20.0f +``` diff --git a/docs/api/math/vector4/one.md b/docs/api/math/vector4/one.md new file mode 100644 index 0000000..bbc06be --- /dev/null +++ b/docs/api/math/vector4/one.md @@ -0,0 +1,17 @@ +# Vector4::One + +```cpp +static Vector4 One() +``` + +返回单位向量 (1, 1, 1, 1)。 + +**返回:** `Vector4` - 值为 (1, 1, 1, 1) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector4 unit = Vector4::One(); +``` diff --git a/docs/api/math/vector4/project.md b/docs/api/math/vector4/project.md new file mode 100644 index 0000000..17b1420 --- /dev/null +++ b/docs/api/math/vector4/project.md @@ -0,0 +1,23 @@ +# Vector4::Project + +```cpp +static Vector4 Project(const Vector4& vector, const Vector4& onNormal) +``` + +将向量投影到法线向量上。 + +**参数:** +- `vector` - 要投影的向量 +- `onNormal` - 投影到的法线向量 + +**返回:** `Vector4` - 投影结果 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector4 v(1.0f, 1.0f, 1.0f, 1.0f); +Vector4 normal(1.0f, 0.0f, 0.0f, 0.0f); +Vector4 projected = Vector4::Project(v, normal); // (1, 0, 0, 0) +``` diff --git a/docs/api/math/vector4/tovector3.md b/docs/api/math/vector4/tovector3.md new file mode 100644 index 0000000..852cc56 --- /dev/null +++ b/docs/api/math/vector4/tovector3.md @@ -0,0 +1,18 @@ +# Vector4::ToVector3 + +```cpp +Vector3 ToVector3() const +``` + +将 Vector4 转换为 Vector3,丢弃 w 分量。 + +**返回:** `Vector3` - 转换后的 Vector3 (x, y, z) + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector4 pos4(1.0f, 2.0f, 3.0f, 1.0f); +Vector3 pos3 = pos4.ToVector3(); // (1, 2, 3) +``` diff --git a/docs/api/math/vector4/vector4.md b/docs/api/math/vector4/vector4.md new file mode 100644 index 0000000..fa8dbf9 --- /dev/null +++ b/docs/api/math/vector4/vector4.md @@ -0,0 +1,53 @@ +# Vector4 + +4D 向量结构体,用于表示齐次坐标、颜色 (RGBA) 或 SIMD 操作。 + +**头文件:** `#include ` + +**命名空间:** `XCEngine::Math` + +## 结构体定义 + +```cpp +struct Vector4 { + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; + float w = 0.0f; +}; +``` + +## 构造函数 + +- `Vector4(float x, float y, float z, float w)` - 从四个分量构造 +- `explicit Vector4(const Vector3& v, float w = 0.0f)` - 从 Vector3 构造 + +## 静态工厂方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Zero()](zero.md) | `Vector4` | 返回 (0, 0, 0, 0) | +| [One()](one.md) | `Vector4` | 返回 (1, 1, 1, 1) | + +## 静态数学方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [Dot(a, b)](dot.md) | `float` | 4D 点积 | +| [Project(vector, onNormal)](project.md) | `Vector4` | 投影 | + +## 实例方法 + +| 方法 | 返回值 | 描述 | +|------|--------|------| +| [ToVector3()](tovector3.md) | `Vector3` | 转换到 Vector3(丢弃 w) | + +## 运算符 + +- 算术: `+`, `-`, `*` (scalar) +- 下标: `operator[]` (0=x, 1=y, 2=z, 3=w) +- 比较: `==`, `!=` + +## 相关文档 + +- [Math 模块总览](../math.md) - 返回 Math 模块总览 diff --git a/docs/api/math/vector4/zero.md b/docs/api/math/vector4/zero.md new file mode 100644 index 0000000..89a11c1 --- /dev/null +++ b/docs/api/math/vector4/zero.md @@ -0,0 +1,17 @@ +# Vector4::Zero + +```cpp +static Vector4 Zero() +``` + +返回零向量 (0, 0, 0, 0)。 + +**返回:** `Vector4` - 值为 (0, 0, 0, 0) 的向量 + +**复杂度:** O(1) + +**示例:** + +```cpp +Vector4 origin = Vector4::Zero(); +``` diff --git a/docs/api/memory/allocator/allocate.md b/docs/api/memory/allocator/allocate.md new file mode 100644 index 0000000..c7c7fbc --- /dev/null +++ b/docs/api/memory/allocator/allocate.md @@ -0,0 +1,38 @@ +# IAllocator::Allocate + +```cpp +virtual void* Allocate(size_t size, size_t alignment = 0) = 0; +``` + +从分配器请求指定大小的内存块。如果 `alignment` 大于 0,则返回的地址将按该对齐值对齐。分配成功时返回有效指针,失败时返回 `nullptr` 或抛出异常(取决于具体实现)。 + +**参数:** +- `size` - 请求的字节数 +- `alignment` - 内存对齐要求,默认为 0(表示使用实现默认对齐) + +**返回:** 分配成功返回已分配内存块的指针,失败返回 `nullptr` + +**复杂度:** O(1)(固定块分配器)或 O(n)(需要搜索合适大小的块) + +**示例:** + +```cpp +#include + +class MyAllocator : public IAllocator { +public: + void* Allocate(size_t size, size_t alignment = 0) override { + // 使用系统 new 分配 + return ::operator new(size); + } + // ... 其他方法实现 +}; + +MyAllocator alloc; +void* ptr = alloc.Allocate(256); // 分配 256 字节 +void* aligned = alloc.Allocate(64, 16); // 分配 64 字节,16 字节对齐 +``` + +## 相关文档 + +- [IAllocator 总览](allocator.md) - 返回类总览 diff --git a/docs/api/memory/allocator/allocator.md b/docs/api/memory/allocator/allocator.md new file mode 100644 index 0000000..5a9f19c --- /dev/null +++ b/docs/api/memory/allocator/allocator.md @@ -0,0 +1,72 @@ +# IAllocator + +**命名空间**: `XCEngine::Memory` + +**类型**: `class` (abstract interface) + +**描述**: 内存分配器抽象接口,定义标准分配协议。 + +## 概述 + +`IAllocator` 是 XCEngine 内存管理系统的核心抽象接口。它定义了分配、释放和重新分配内存的标准方法,以及内存统计接口。所有专用分配器(LinearAllocator、PoolAllocator、ProxyAllocator)都实现此接口。 + +## 公共方法 + +### 内存操作 + +| 方法 | 描述 | +|------|------| +| `Allocate` | 分配内存 | +| `Free` | 释放内存 | +| `Reallocate` | 重新分配内存 | + +### 统计信息 + +| 方法 | 描述 | +|------|------| +| `GetTotalAllocated` | 获取已分配总字节数 | +| `GetTotalFreed` | 获取已释放总字节数 | +| `GetPeakAllocated` | 获取峰值分配字节数 | +| `GetAllocationCount` | 获取分配次数 | + +### 元信息 + +| 方法 | 描述 | +|------|------| +| `GetName` | 获取分配器名称 | + +## 使用示例 + +```cpp +#include + +class MyAllocator : public IAllocator { +public: + void* Allocate(size_t size, size_t alignment = 0) override { + return ::operator new(size); + } + + void Free(void* ptr) override { + ::operator delete(ptr); + } + + void* Reallocate(void* ptr, size_t newSize) override { + void* newPtr = Allocate(newSize); + Free(ptr); + return newPtr; + } + + size_t GetTotalAllocated() const override { return m_allocated; } + size_t GetTotalFreed() const override { return m_freed; } + size_t GetPeakAllocated() const override { return m_peak; } + size_t GetAllocationCount() const override { return m_count; } + const char* GetName() const override { return "MyAllocator"; } +}; +``` + +## 相关文档 + +- [Memory 模块总览](../memory.md) - 返回模块总览 +- [MemoryManager](../manager/manager.md) - 内存管理器 +- [LinearAllocator](../linear-allocator/linear-allocator.md) - 线性分配器 +- [PoolAllocator](../pool-allocator/pool-allocator.md) - 内存池分配器 diff --git a/docs/api/memory/allocator/free.md b/docs/api/memory/allocator/free.md new file mode 100644 index 0000000..172fff4 --- /dev/null +++ b/docs/api/memory/allocator/free.md @@ -0,0 +1,40 @@ +# IAllocator::Free + +```cpp +virtual void Free(void* ptr) = 0; +``` + +释放之前通过 `Allocate` 分配的内存块。如果 `ptr` 为 `nullptr`,则此调用无效果。部分分配器(如 LinearAllocator)可能不支持此操作。 + +**参数:** +- `ptr` - 指向要释放内存块的指针 + +**返回:** 无 + +**复杂度:** O(1)(固定块释放)或 O(n)(需要搜索) + +**示例:** + +```cpp +#include + +class MyAllocator : public IAllocator { +public: + void* Allocate(size_t size, size_t alignment = 0) override { + return ::operator new(size); + } + + void Free(void* ptr) override { + if (ptr) ::operator delete(ptr); + } + // ... 其他方法实现 +}; + +MyAllocator alloc; +void* ptr = alloc.Allocate(512); +alloc.Free(ptr); // 释放内存 +``` + +## 相关文档 + +- [IAllocator 总览](allocator.md) - 返回类总览 diff --git a/docs/api/memory/allocator/get-allocation-count.md b/docs/api/memory/allocator/get-allocation-count.md new file mode 100644 index 0000000..627e9cc --- /dev/null +++ b/docs/api/memory/allocator/get-allocation-count.md @@ -0,0 +1,52 @@ +# IAllocator::GetAllocationCount + +```cpp +virtual size_t GetAllocationCount() const = 0; +``` + +返回当前处于已分配状态(未释放)的内存块数量。此方法用于监控活跃分配的数量。 + +**参数:** 无 + +**返回:** 当前已分配块的数量 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +class MyAllocator : public IAllocator { + size_t m_count = 0; +public: + void* Allocate(size_t size, size_t alignment = 0) override { + ++m_count; + return ::operator new(size); + } + + void Free(void* ptr) override { + if (ptr) { + --m_count; + ::operator delete(ptr); + } + } + + void* Reallocate(void* ptr, size_t newSize) override { /* ... */ } + + size_t GetTotalAllocated() const override { return 0; } + size_t GetTotalFreed() const override { return 0; } + size_t GetPeakAllocated() const override { return 0; } + size_t GetAllocationCount() const override { return m_count; } + const char* GetName() const override { return "MyAllocator"; } +}; + +MyAllocator alloc; +alloc.Allocate(64); +alloc.Allocate(128); +size_t count = alloc.GetAllocationCount(); // 返回 2 +``` + +## 相关文档 + +- [IAllocator 总览](allocator.md) - 返回类总览 diff --git a/docs/api/memory/allocator/get-name.md b/docs/api/memory/allocator/get-name.md new file mode 100644 index 0000000..47155e1 --- /dev/null +++ b/docs/api/memory/allocator/get-name.md @@ -0,0 +1,40 @@ +# IAllocator::GetName + +```cpp +virtual const char* GetName() const = 0; +``` + +返回分配器的名称字符串。此方法用于调试、日志记录和内存报告,帮助识别不同分配器的使用情况。 + +**参数:** 无 + +**返回:** 分配器的名称字符串 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +class MyAllocator : public IAllocator { +public: + void* Allocate(size_t size, size_t alignment = 0) override { return ::operator new(size); } + void Free(void* ptr) override { if (ptr) ::operator delete(ptr); } + void* Reallocate(void* ptr, size_t newSize) override { /* ... */ } + + size_t GetTotalAllocated() const override { return 0; } + size_t GetTotalFreed() const override { return 0; } + size_t GetPeakAllocated() const override { return 0; } + size_t GetAllocationCount() const override { return 0; } + const char* GetName() const override { return "MyAllocator"; } +}; + +MyAllocator alloc; +const char* name = alloc.GetName(); // 返回 "MyAllocator" +printf("Allocator: %s\n", name); +``` + +## 相关文档 + +- [IAllocator 总览](allocator.md) - 返回类总览 diff --git a/docs/api/memory/allocator/get-peak-allocated.md b/docs/api/memory/allocator/get-peak-allocated.md new file mode 100644 index 0000000..da1f31e --- /dev/null +++ b/docs/api/memory/allocator/get-peak-allocated.md @@ -0,0 +1,57 @@ +# IAllocator::GetPeakAllocated + +```cpp +virtual size_t GetPeakAllocated() const = 0; +``` + +返回此分配器自创建以来达到的峰值分配字节数。该值在每次分配后更新,用于监控内存使用高峰。 + +**参数:** 无 + +**返回:** 峰值分配字节数 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +class MyAllocator : public IAllocator { + size_t m_peak = 0; + size_t m_current = 0; +public: + void* Allocate(size_t size, size_t alignment = 0) override { + void* ptr = ::operator new(size); + m_current += size; + if (m_current > m_peak) m_peak = m_current; + return ptr; + } + + void Free(void* ptr) override { + if (ptr) { + size_t size = 256; // 需要外部记录 + ::operator delete(ptr); + m_current -= size; + } + } + + void* Reallocate(void* ptr, size_t newSize) override { /* ... */ } + + size_t GetTotalAllocated() const override { return 0; } + size_t GetTotalFreed() const override { return 0; } + size_t GetPeakAllocated() const override { return m_peak; } + size_t GetAllocationCount() const override { return 0; } + const char* GetName() const override { return "MyAllocator"; } +}; + +MyAllocator alloc; +alloc.Allocate(100); +size_t peak1 = alloc.GetPeakAllocated(); // 100 +alloc.Allocate(50); +size_t peak2 = alloc.GetPeakAllocated(); // 150 +``` + +## 相关文档 + +- [IAllocator 总览](allocator.md) - 返回类总览 diff --git a/docs/api/memory/allocator/get-total-allocated.md b/docs/api/memory/allocator/get-total-allocated.md new file mode 100644 index 0000000..182b844 --- /dev/null +++ b/docs/api/memory/allocator/get-total-allocated.md @@ -0,0 +1,50 @@ +# IAllocator::GetTotalAllocated + +```cpp +virtual size_t GetTotalAllocated() const = 0; +``` + +返回此分配器自创建以来累计分配的字节总数。这是一个只读查询操作,不会修改任何内部状态。 + +**参数:** 无 + +**返回:** 累计已分配的字节数 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +class MyAllocator : public IAllocator { + size_t m_allocated = 0; +public: + void* Allocate(size_t size, size_t alignment = 0) override { + void* ptr = ::operator new(size); + m_allocated += size; + return ptr; + } + + void Free(void* ptr) override { + if (ptr) ::operator delete(ptr); + } + + void* Reallocate(void* ptr, size_t newSize) override { /* ... */ } + + size_t GetTotalAllocated() const override { return m_allocated; } + size_t GetTotalFreed() const override { return 0; } + size_t GetPeakAllocated() const override { return m_allocated; } + size_t GetAllocationCount() const override { return 0; } + const char* GetName() const override { return "MyAllocator"; } +}; + +MyAllocator alloc; +alloc.Allocate(100); +alloc.Allocate(200); +size_t total = alloc.GetTotalAllocated(); // 返回 300 +``` + +## 相关文档 + +- [IAllocator 总览](allocator.md) - 返回类总览 diff --git a/docs/api/memory/allocator/get-total-freed.md b/docs/api/memory/allocator/get-total-freed.md new file mode 100644 index 0000000..4f1d5bd --- /dev/null +++ b/docs/api/memory/allocator/get-total-freed.md @@ -0,0 +1,50 @@ +# IAllocator::GetTotalFreed + +```cpp +virtual size_t GetTotalFreed() const = 0; +``` + +返回此分配器自创建以来累计释放的字节总数。部分分配器(如 LinearAllocator)可能始终返回 0,因为它们不跟踪单个释放操作。 + +**参数:** 无 + +**返回:** 累计已释放的字节数 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +class MyAllocator : public IAllocator { + size_t m_freed = 0; +public: + void* Allocate(size_t size, size_t alignment = 0) override { return ::operator new(size); } + + void Free(void* ptr) override { + if (ptr) { + size_t size = 256; // 需要外部记录 + ::operator delete(ptr); + m_freed += size; + } + } + + void* Reallocate(void* ptr, size_t newSize) override { /* ... */ } + + size_t GetTotalAllocated() const override { return 0; } + size_t GetTotalFreed() const override { return m_freed; } + size_t GetPeakAllocated() const override { return 0; } + size_t GetAllocationCount() const override { return 0; } + const char* GetName() const override { return "MyAllocator"; } +}; + +MyAllocator alloc; +void* ptr = alloc.Allocate(128); +alloc.Free(ptr); +size_t freed = alloc.GetTotalFreed(); // 返回 128 +``` + +## 相关文档 + +- [IAllocator 总览](allocator.md) - 返回类总览 diff --git a/docs/api/memory/allocator/reallocate.md b/docs/api/memory/allocator/reallocate.md new file mode 100644 index 0000000..345fbba --- /dev/null +++ b/docs/api/memory/allocator/reallocate.md @@ -0,0 +1,55 @@ +# IAllocator::Reallocate + +```cpp +virtual void* Reallocate(void* ptr, size_t newSize) = 0; +``` + +调整已分配内存块的大小。如果 `ptr` 为 `nullptr`,行为等同于 `Allocate(newSize)`。如果 `newSize` 为 0,行为等同于 `Free(ptr)` 并返回 `nullptr`。如果分配器不支持重新分配,应返回 `nullptr` 并保持原内存不变。 + +**参数:** +- `ptr` - 指向现有内存块的指针 +- `newSize` - 新的字节大小 + +**返回:** 调整后的新内存块指针(可能与原指针不同) + +**复杂度:** O(n),需要分配新内存并复制数据 + +**示例:** + +```cpp +#include + +class MyAllocator : public IAllocator { +public: + void* Allocate(size_t size, size_t alignment = 0) override { + return ::operator new(size); + } + + void Free(void* ptr) override { + if (ptr) ::operator delete(ptr); + } + + void* Reallocate(void* ptr, size_t newSize) override { + if (newSize == 0) { + Free(ptr); + return nullptr; + } + if (!ptr) return Allocate(newSize); + + size_t oldSize = /* 需要外部记录 */ 256; // 示例中硬编码 + void* newPtr = Allocate(newSize); + memcpy(newPtr, ptr, oldSize < newSize ? oldSize : newSize); + Free(ptr); + return newPtr; + } + // ... 其他方法实现 +}; + +MyAllocator alloc; +void* ptr = alloc.Allocate(128); +void* bigger = alloc.Reallocate(ptr, 256); // 扩展到 256 字节 +``` + +## 相关文档 + +- [IAllocator 总览](allocator.md) - 返回类总览 diff --git a/docs/api/memory/linear-allocator/allocate.md b/docs/api/memory/linear-allocator/allocate.md new file mode 100644 index 0000000..228dec2 --- /dev/null +++ b/docs/api/memory/linear-allocator/allocate.md @@ -0,0 +1,41 @@ +# LinearAllocator::Allocate + +```cpp +void* Allocate(size_t size, size_t alignment = 8) override; +``` + +在缓冲区的当前位置顺序分配内存。每次分配都会将内部偏移量向前推进(对齐后)。如果剩余空间不足,则分配失败返回 `nullptr`。默认对齐值为 8 字节。 + +**参数:** +- `size` - 请求的字节数 +- `alignment` - 内存对齐要求,默认为 8 字节 + +**返回:** 分配成功返回已对齐的指针,失败返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +LinearAllocator allocator(1024); + +// 分配 256 字节(8 字节对齐) +void* ptr1 = allocator.Allocate(256); + +// 分配 128 字节(16 字节对齐) +void* ptr2 = allocator.Allocate(128, 16); + +// 分配 64 字节(默认 8 字节对齐) +void* ptr3 = allocator.Allocate(64); + +// 检查是否成功 +if (!ptr1) { + // 分配失败,缓冲区已满 +} +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 diff --git a/docs/api/memory/linear-allocator/clear.md b/docs/api/memory/linear-allocator/clear.md new file mode 100644 index 0000000..6a6f879 --- /dev/null +++ b/docs/api/memory/linear-allocator/clear.md @@ -0,0 +1,37 @@ +# LinearAllocator::Clear + +```cpp +void Clear(); +``` + +清空分配器,将内部偏移量重置为 0,所有已分配的内存被视为已释放。下一次 `Allocate` 将从缓冲区起始位置开始。此方法不实际释放或修改底层内存,适合作为帧分配器使用,每帧开始时调用 Clear 重置。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +LinearAllocator allocator(1024 * 1024); + +// 第一帧 +void* frame1_ptr = allocator.Allocate(256); +void* frame1_ptr2 = allocator.Allocate(128); +// ... 第一帧渲染逻辑 + +// 帧结束时清空 +allocator.Clear(); + +// 第二帧重新开始 +void* frame2_ptr = allocator.Allocate(256); +// 此时 frame1_ptr 已无效,但内存已被回收复用 +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 diff --git a/docs/api/memory/linear-allocator/free.md b/docs/api/memory/linear-allocator/free.md new file mode 100644 index 0000000..0b6e491 --- /dev/null +++ b/docs/api/memory/linear-allocator/free.md @@ -0,0 +1,35 @@ +# LinearAllocator::Free + +```cpp +void Free(void* ptr) override; +``` + +此方法对 LinearAllocator 无实际效果。线性分配器不支持单个内存块的释放,因为内存是顺序分配的,释放中间某块会破坏后续分配的完整性。需要释放所有内存时使用 `Clear()` 方法。 + +**参数:** +- `ptr` - 被忽略 + +**返回:** 无 + +**复杂度:** O(1)(空操作) + +**示例:** + +```cpp +#include + +LinearAllocator allocator(1024); +void* ptr = allocator.Allocate(256); +void* ptr2 = allocator.Allocate(128); + +// Free 实际上什么都不做 +allocator.Free(ptr); +allocator.Free(ptr2); + +// 如需释放所有内存,应使用 Clear +allocator.Clear(); +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 diff --git a/docs/api/memory/linear-allocator/get-capacity.md b/docs/api/memory/linear-allocator/get-capacity.md new file mode 100644 index 0000000..23fdbcf --- /dev/null +++ b/docs/api/memory/linear-allocator/get-capacity.md @@ -0,0 +1,33 @@ +# LinearAllocator::GetCapacity + +```cpp +size_t GetCapacity() const; +``` + +返回分配器的总容量,即预分配缓冲区的大小。此值在构造时确定,之后保持不变。 + +**参数:** 无 + +**返回:** 总容量(字节数) + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +LinearAllocator allocator(1024 * 1024); // 1MB + +size_t capacity = allocator.GetCapacity(); // 1048576 + +allocator.Allocate(512); +allocator.Allocate(256); + +size_t used = allocator.GetUsedSize(); // 768 +size_t remaining = allocator.GetCapacity() - allocator.GetUsedSize(); // 1047808 +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 diff --git a/docs/api/memory/linear-allocator/get-marker.md b/docs/api/memory/linear-allocator/get-marker.md new file mode 100644 index 0000000..73bcf41 --- /dev/null +++ b/docs/api/memory/linear-allocator/get-marker.md @@ -0,0 +1,43 @@ +# LinearAllocator::GetMarker + +```cpp +void* GetMarker() const; +``` + +获取当前分配位置的标记。标记是内部偏移量(`m_offset`)的快照,可用于 `SetMarker` 恢复到该位置。此方法用于实现临时分配的撤销功能。 + +**参数:** 无 + +**返回:** 当前位置标记(偏移量值),类型为 `void*` + +**注意:** 返回值是偏移量数值,不是指针。将其传给 `SetMarker` 可恢复到此分配位置。 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +LinearAllocator allocator(1024); + +// 分配一些数据 +void* ptr1 = allocator.Allocate(128); + +// 保存标记(用于回滚点) +void* marker = allocator.GetMarker(); + +// 分配临时数据 +void* temp = allocator.Allocate(64); +void* temp2 = allocator.Allocate(32); + +// 临时数据用完了,恢复到标记位置 +allocator.SetMarker(marker); + +// 此时 temp 和 temp2 的内存已被回收 +// ptr1 仍然有效 +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 diff --git a/docs/api/memory/linear-allocator/get-used-size.md b/docs/api/memory/linear-allocator/get-used-size.md new file mode 100644 index 0000000..898859b --- /dev/null +++ b/docs/api/memory/linear-allocator/get-used-size.md @@ -0,0 +1,39 @@ +# LinearAllocator::GetUsedSize + +```cpp +size_t GetUsedSize() const; +``` + +返回当前已使用的字节数,即内部偏移量的值。此值在 `Allocate` 后增加,在 `Clear` 或 `SetMarker` 后可能减少(取决于设置的目标位置)。 + +**参数:** 无 + +**返回:** 已使用的字节数 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +LinearAllocator allocator(1024); + +size_t before = allocator.GetUsedSize(); // 0 + +allocator.Allocate(128); +allocator.Allocate(256); + +size_t after = allocator.GetUsedSize(); // 384 + +void* marker = allocator.GetMarker(); +allocator.Allocate(64); +size_t with_temp = allocator.GetUsedSize(); // 448 + +allocator.SetMarker(marker); +size_t after_rollback = allocator.GetUsedSize(); // 384 +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 diff --git a/docs/api/memory/linear-allocator/linear-allocator.md b/docs/api/memory/linear-allocator/linear-allocator.md new file mode 100644 index 0000000..5da70dd --- /dev/null +++ b/docs/api/memory/linear-allocator/linear-allocator.md @@ -0,0 +1,66 @@ +# LinearAllocator + +**命名空间**: `XCEngine::Memory` + +**类型**: `class` + +**描述**: 线性分配器,适合帧分配和临时对象。 + +## 概述 + +`LinearAllocator` 是一种顺序分配器,预分配一个大缓冲区,每次分配从缓冲区起始位置顺序分配,偏移量递增。它不适合需要释放任意块的场景,但分配和清除非常高效,常用于帧分配器。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `LinearAllocator` | 构造线性分配器 | +| `~LinearAllocator` | 析构函数,释放底层缓冲区 | +| `Allocate` | 顺序分配内存 | +| `Free` | 无效果(不支持) | +| `Reallocate` | 不支持(始终返回 nullptr) | +| `Clear` | 清空所有分配 | +| `GetMarker` | 获取当前位置标记 | +| `SetMarker` | 回滚到指定标记位置 | +| `GetUsedSize` | 获取已使用字节数 | +| `GetCapacity` | 获取总容量 | + +## 构造函数 + +```cpp +explicit LinearAllocator(size_t size, IAllocator* parent = nullptr); +~LinearAllocator() override; +``` + +构造一个线性分配器,预分配指定大小的缓冲区。如果提供了 `parent` 分配器,则使用它分配底层缓冲区;否则使用系统默认分配(`_aligned_malloc`,8 字节对齐)。 + +**参数:** +- `size` - 预分配的缓冲区大小(字节数) +- `parent` - 父分配器,用于分配底层缓冲区,默认为 `nullptr`(使用系统分配) + +**返回:** 无 + +**复杂度:** O(n),需要分配 `size` 大小的缓冲区 + +**注意:** `Free` 和 `Reallocate` 方法无实际效果。`Free` 是空操作,`Reallocate` 始终返回 `nullptr`。 + +**示例:** + +```cpp +#include + +// 使用系统分配器创建 1MB 线性分配器 +LinearAllocator allocator1(1024 * 1024); + +// 使用指定的父分配器 +IAllocator* parent = MemoryManager::Get().GetSystemAllocator(); +LinearAllocator allocator2(1024 * 1024, parent); + +// 默认 8 字节对齐 +void* ptr = allocator1.Allocate(256); +``` + +## 相关文档 + +- [Memory 模块总览](../memory.md) - 返回模块总览 +- [IAllocator](../allocator/allocator.md) - 分配器接口 diff --git a/docs/api/memory/linear-allocator/reallocate.md b/docs/api/memory/linear-allocator/reallocate.md new file mode 100644 index 0000000..ec4fd1b --- /dev/null +++ b/docs/api/memory/linear-allocator/reallocate.md @@ -0,0 +1,35 @@ +# LinearAllocator::Reallocate + +```cpp +void* Reallocate(void* ptr, size_t newSize) override; +``` + +线性分配器不支持重新分配。此方法始终返回 `nullptr`,原内存块保持不变。由于线性分配器的顺序分配特性,无法调整现有块的大小。 + +**参数:** +- `ptr` - 不被使用(始终返回 nullptr) +- `newSize` - 不被使用(始终返回 nullptr) + +**返回:** 始终返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +LinearAllocator allocator(1024); +void* ptr1 = allocator.Allocate(128); + +// Reallocate 不支持,始终返回 nullptr +void* ptr2 = allocator.Reallocate(ptr1, 256); +if (!ptr2) { + // 线性分配器不支持重新分配 + // ptr1 仍然有效 +} +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 diff --git a/docs/api/memory/linear-allocator/set-marker.md b/docs/api/memory/linear-allocator/set-marker.md new file mode 100644 index 0000000..b2fa937 --- /dev/null +++ b/docs/api/memory/linear-allocator/set-marker.md @@ -0,0 +1,41 @@ +# LinearAllocator::SetMarker + +```cpp +void SetMarker(void* marker); +``` + +恢复到之前通过 `GetMarker` 获取的标记位置。所有在标记之后的分配都将被丢弃,内部偏移量重置为该标记位置。此方法不会释放内存,只是移动偏移量指针。 + +**参数:** +- `marker` - 通过 `GetMarker` 获取的标记指针 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +LinearAllocator allocator(1024); + +// 基础数据 +void* base = allocator.Allocate(256); +void* marker = allocator.GetMarker(); + +// 可选的扩展数据 +void* ext1 = allocator.Allocate(64); +void* ext2 = allocator.Allocate(128); + +// 决定不使用扩展数据,回滚 +allocator.SetMarker(marker); + +// 扩展数据内存已被回收 +// 可以重新分配其他数据 +void* new_data = allocator.Allocate(128); +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 diff --git a/docs/api/memory/linear-allocator/~linear-allocator.md b/docs/api/memory/linear-allocator/~linear-allocator.md new file mode 100644 index 0000000..b7c2384 --- /dev/null +++ b/docs/api/memory/linear-allocator/~linear-allocator.md @@ -0,0 +1,29 @@ +# LinearAllocator::~LinearAllocator + +```cpp +~LinearAllocator() override; +``` + +销毁线性分配器,释放预分配的缓冲区。如果提供了 `parent` 分配器,则使用它释放缓冲区;否则使用系统默认释放(`::operator delete`)。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +{ + LinearAllocator allocator(1024 * 1024); + void* ptr = allocator.Allocate(256); + // ... 使用 allocator +} // 析构时自动释放 1MB 缓冲区 +``` + +## 相关文档 + +- [LinearAllocator 总览](linear-allocator.md) - 返回类总览 diff --git a/docs/api/memory/manager/create-linear-allocator.md b/docs/api/memory/manager/create-linear-allocator.md new file mode 100644 index 0000000..c0475b6 --- /dev/null +++ b/docs/api/memory/manager/create-linear-allocator.md @@ -0,0 +1,32 @@ +# MemoryManager::CreateLinearAllocator + +```cpp +std::unique_ptr CreateLinearAllocator(size_t size); +``` + +创建并返回一个新的 LinearAllocator 实例,使用系统分配器作为底层。返回的 `unique_ptr` 管理分配器生命周期。 + +**参数:** +- `size` - 分配器缓冲区大小(字节) + +**返回:** LinearAllocator 的 unique_ptr + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +auto linear = MemoryManager::Get().CreateLinearAllocator(1024 * 1024); +void* ptr = linear->Allocate(256); +void* marker = linear->GetMarker(); +linear->Allocate(128); +linear->SetMarker(marker); +linear->Clear(); +``` + +## 相关文档 + +- [MemoryManager 总览](manager.md) - 返回类总览 +- [LinearAllocator](../linear-allocator/linear-allocator.md) - 线性分配器 diff --git a/docs/api/memory/manager/create-pool-allocator.md b/docs/api/memory/manager/create-pool-allocator.md new file mode 100644 index 0000000..4f096d5 --- /dev/null +++ b/docs/api/memory/manager/create-pool-allocator.md @@ -0,0 +1,37 @@ +# MemoryManager::CreatePoolAllocator + +```cpp +std::unique_ptr CreatePoolAllocator(size_t blockSize, size_t count); +``` + +创建并返回一个新的 PoolAllocator 实例,使用系统分配器作为底层。返回的 `unique_ptr` 管理分配器生命周期。 + +**参数:** +- `blockSize` - 每个内存块的大小(字节) +- `count` - 内存池中块的数量 + +**返回:** PoolAllocator 的 unique_ptr + +**复杂度:** O(blockSize * count)(需要预分配所有块) + +**示例:** + +```cpp +#include + +struct Particle { + float x, y, z; + float life; +}; + +auto pool = MemoryManager::Get().CreatePoolAllocator(sizeof(Particle), 1000); +void* block = pool->Allocate(); +auto* p = new (block) Particle{1.0f, 2.0f, 3.0f, 5.0f}; +p->~Particle(); +pool->Free(block); +``` + +## 相关文档 + +- [MemoryManager 总览](manager.md) - 返回类总览 +- [PoolAllocator](../pool-allocator/pool-allocator.md) - 内存池分配器 diff --git a/docs/api/memory/manager/create-proxy-allocator.md b/docs/api/memory/manager/create-proxy-allocator.md new file mode 100644 index 0000000..de9bb5e --- /dev/null +++ b/docs/api/memory/manager/create-proxy-allocator.md @@ -0,0 +1,36 @@ +# MemoryManager::CreateProxyAllocator + +```cpp +std::unique_ptr CreateProxyAllocator(const char* name); +``` + +创建并返回一个新的 ProxyAllocator 实例,包装系统分配器并使用指定名称。返回的 `unique_ptr` 管理分配器生命周期。 + +**参数:** +- `name` - 代理分配器的名称 + +**返回:** ProxyAllocator 的 unique_ptr + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +auto proxy = MemoryManager::Get().CreateProxyAllocator("FrameData"); +void* ptr = proxy->Allocate(1024); +void* ptr2 = proxy->Allocate(512); + +const auto& stats = proxy->GetStats(); +printf("Peak: %zu bytes, Count: %zu\n", + stats.peakAllocated, stats.allocationCount); + +proxy->Free(ptr); +proxy->Free(ptr2); +``` + +## 相关文档 + +- [MemoryManager 总览](manager.md) - 返回类总览 +- [ProxyAllocator](../proxy-allocator/proxy-allocator.md) - 代理分配器 diff --git a/docs/api/memory/manager/dump-memory-leaks.md b/docs/api/memory/manager/dump-memory-leaks.md new file mode 100644 index 0000000..3ec9f1d --- /dev/null +++ b/docs/api/memory/manager/dump-memory-leaks.md @@ -0,0 +1,31 @@ +# MemoryManager::DumpMemoryLeaks + +```cpp +void DumpMemoryLeaks(); +``` + +输出当前未释放的内存分配信息。如果启用了内存跟踪,此方法会遍历所有记录并报告疑似泄漏的分配。应在程序退出前调用,以便发现资源泄漏。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +#include + +MemoryManager::Get().Initialize(); + +// ... 程序运行 ... + +// 程序退出前检查泄漏 +MemoryManager::Get().DumpMemoryLeaks(); +MemoryManager::Get().Shutdown(); +``` + +## 相关文档 + +- [MemoryManager 总览](manager.md) - 返回类总览 diff --git a/docs/api/memory/manager/generate-memory-report.md b/docs/api/memory/manager/generate-memory-report.md new file mode 100644 index 0000000..b665957 --- /dev/null +++ b/docs/api/memory/manager/generate-memory-report.md @@ -0,0 +1,37 @@ +# MemoryManager::GenerateMemoryReport + +```cpp +void GenerateMemoryReport(); +``` + +生成并输出当前内存使用情况的详细报告。报告内容包括各分配器的统计信息、峰值使用量、分配次数等。应在启用内存跟踪后调用。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +#include + +MemoryManager::Get().Initialize(); + +auto proxy = MemoryManager::Get().CreateProxyAllocator("GameFrame"); +proxy->Allocate(1024 * 1024); +proxy->Allocate(512 * 1024); + +// 生成内存报告 +MemoryManager::Get().GenerateMemoryReport(); + +proxy->Free(proxy->Allocate(256 * 1024)); +MemoryManager::Get().GenerateMemoryReport(); + +MemoryManager::Get().Shutdown(); +``` + +## 相关文档 + +- [MemoryManager 总览](manager.md) - 返回类总览 diff --git a/docs/api/memory/manager/get-system-allocator.md b/docs/api/memory/manager/get-system-allocator.md new file mode 100644 index 0000000..34a3ebd --- /dev/null +++ b/docs/api/memory/manager/get-system-allocator.md @@ -0,0 +1,27 @@ +# MemoryManager::GetSystemAllocator + +```cpp +IAllocator* GetSystemAllocator(); +``` + +获取系统默认分配器。该分配器使用标准 C 库的 `std::malloc` 和平台特定的对齐分配函数(如 Windows 的 `_aligned_malloc`)作为后端,适用于通用内存分配场景。 + +**参数:** 无 + +**返回:** 系统分配器指针 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); +void* ptr = sysAlloc->Allocate(1024); +sysAlloc->Free(ptr); +``` + +## 相关文档 + +- [MemoryManager 总览](manager.md) - 返回类总览 diff --git a/docs/api/memory/manager/get.md b/docs/api/memory/manager/get.md new file mode 100644 index 0000000..c4eb11c --- /dev/null +++ b/docs/api/memory/manager/get.md @@ -0,0 +1,39 @@ +# MemoryManager::Get + +```cpp +static MemoryManager& Get(); +``` + +获取 MemoryManager 单例实例。如果尚未创建则内部构造。此方法是获取内存管理器实例的唯一途径。 + +**参数:** 无 + +**返回:** MemoryManager 单例引用 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +// 获取单例 +MemoryManager& manager = MemoryManager::Get(); + +// 初始化 +manager.Initialize(); + +// 访问系统分配器 +IAllocator* sysAlloc = manager.GetSystemAllocator(); + +// 关闭 +manager.Shutdown(); + +// 多次调用返回同一实例 +MemoryManager& manager2 = MemoryManager::Get(); +// manager == manager2 为 true +``` + +## 相关文档 + +- [MemoryManager 总览](manager.md) - 返回类总览 diff --git a/docs/api/memory/manager/initialize.md b/docs/api/memory/manager/initialize.md new file mode 100644 index 0000000..c95c046 --- /dev/null +++ b/docs/api/memory/manager/initialize.md @@ -0,0 +1,33 @@ +# MemoryManager::Initialize + +```cpp +void Initialize(); +``` + +初始化内存管理器。创建系统默认分配器,设置内存跟踪标志。应在程序启动早期调用,且仅可调用一次。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +#include + +int main() { + // 程序启动时初始化 + MemoryManager::Get().Initialize(); + + // 使用内存系统... + + MemoryManager::Get().Shutdown(); + return 0; +} +``` + +## 相关文档 + +- [MemoryManager 总览](manager.md) - 返回类总览 diff --git a/docs/api/memory/manager/manager.md b/docs/api/memory/manager/manager.md new file mode 100644 index 0000000..10061e2 --- /dev/null +++ b/docs/api/memory/manager/manager.md @@ -0,0 +1,85 @@ +# MemoryManager + +**命名空间**: `XCEngine::Memory` + +**类型**: `class` (singleton) + +**描述**: 全局内存管理器单例,提供系统分配器和各种专用分配器的创建。 + +## 概述 + +`MemoryManager` 是 XCEngine 内存管理系统的核心单例。它负责维护系统分配器,提供分配器工厂方法,并支持内存泄漏检测和报告。 + +## 单例访问 + +| 方法 | 描述 | +|------|------| +| `Get` | 获取单例实例 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `Initialize` | 初始化内存管理器 | +| `Shutdown` | 关闭内存管理器 | +| `GetSystemAllocator` | 获取系统默认分配器 | +| `CreateLinearAllocator` | 创建线性分配器 | +| `CreatePoolAllocator` | 创建内存池分配器 | +| `CreateProxyAllocator` | 创建代理分配器 | +| `SetTrackAllocations` | 设置是否跟踪分配 | +| `DumpMemoryLeaks` | 输出内存泄漏报告 | +| `GenerateMemoryReport` | 生成内存使用报告 | + +## 宏定义 + +### XE_ALLOC + +```cpp +#define XE_ALLOC(allocator, size, ...) allocator->Allocate(size, ##__VA_ARGS__) +``` + +内存分配宏。 + +### XE_FREE + +```cpp +#define XE_FREE(allocator, ptr) allocator->Free(ptr) +``` + +内存释放宏。 + +## 使用示例 + +```cpp +#include + +// 初始化 +MemoryManager::Get().Initialize(); + +// 获取系统分配器 +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); + +// 创建专用分配器 +auto linearAlloc = MemoryManager::Get().CreateLinearAllocator(1024 * 1024); +auto poolAlloc = MemoryManager::Get().CreatePoolAllocator(sizeof(MyObject), 1000); +auto proxyAlloc = MemoryManager::Get().CreateProxyAllocator("GameFrame"); + +// 使用宏分配 +void* ptr = XE_ALLOC(proxyAlloc, 256); +XE_FREE(proxyAlloc, ptr); + +// 跟踪内存 +MemoryManager::Get().SetTrackAllocations(true); +MemoryManager::Get().GenerateMemoryReport(); + +// 关闭 +MemoryManager::Get().Shutdown(); +``` + +## 相关文档 + +- [Memory 模块总览](../memory.md) - 返回模块总览 +- [IAllocator](../allocator/allocator.md) - 分配器接口 +- [LinearAllocator](../linear-allocator/linear-allocator.md) - 线性分配器 +- [PoolAllocator](../pool-allocator/pool-allocator.md) - 内存池分配器 +- [ProxyAllocator](../proxy-allocator/proxy-allocator.md) - 代理分配器 diff --git a/docs/api/memory/manager/set-track-allocations.md b/docs/api/memory/manager/set-track-allocations.md new file mode 100644 index 0000000..2b55999 --- /dev/null +++ b/docs/api/memory/manager/set-track-allocations.md @@ -0,0 +1,35 @@ +# MemoryManager::SetTrackAllocations + +```cpp +void SetTrackAllocations(bool track); +``` + +设置是否启用内存分配跟踪。启用后系统会记录所有分配操作,用于生成内存报告和泄漏检测。 + +**参数:** +- `track` - true 启用跟踪,false 禁用跟踪 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +MemoryManager::Get().Initialize(); + +// 禁用跟踪(提升性能) +MemoryManager::Get().SetTrackAllocations(false); + +// ... 大量内存操作 ... + +// 重新启用跟踪进行分析 +MemoryManager::Get().SetTrackAllocations(true); +MemoryManager::Get().GenerateMemoryReport(); +``` + +## 相关文档 + +- [MemoryManager 总览](manager.md) - 返回类总览 diff --git a/docs/api/memory/manager/shutdown.md b/docs/api/memory/manager/shutdown.md new file mode 100644 index 0000000..f631f5b --- /dev/null +++ b/docs/api/memory/manager/shutdown.md @@ -0,0 +1,35 @@ +# MemoryManager::Shutdown + +```cpp +void Shutdown(); +``` + +关闭内存管理器。执行内存泄漏检测报告,释放系统分配器。应在程序退出前调用。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +#include + +int main() { + MemoryManager::Get().Initialize(); + + // ... 游戏主循环 ... + + // 程序退出前关闭 + MemoryManager::Get().DumpMemoryLeaks(); + MemoryManager::Get().Shutdown(); + + return 0; +} +``` + +## 相关文档 + +- [MemoryManager 总览](manager.md) - 返回类总览 diff --git a/docs/api/memory/memory.md b/docs/api/memory/memory.md new file mode 100644 index 0000000..dae159f --- /dev/null +++ b/docs/api/memory/memory.md @@ -0,0 +1,72 @@ +# Memory 模块概览 + +**命名空间**: `XCEngine::Memory` + +**类型**: `module` + +**描述**: XCEngine 的内存管理模块,提供多种内存分配器实现。 + +## 概述 + +Memory 模块提供了一套完整的内存管理解决方案,包括基础分配器接口和各种专用分配器实现。 + +## 模块内容 + +### 分配器接口 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [IAllocator](allocator/allocator.md) | `Allocator.h` | 内存分配器抽象接口 | + +### 分配器实现 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [LinearAllocator](linear-allocator/linear-allocator.md) | `LinearAllocator.h` | 线性分配器,适合帧分配 | +| [PoolAllocator](pool-allocator/pool-allocator.md) | `PoolAllocator.h` | 内存池分配器,适合固定大小对象 | +| [ProxyAllocator](proxy-allocator/proxy-allocator.md) | `ProxyAllocator.h` | 代理分配器,用于统计和跟踪 | + +### 管理器 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [MemoryManager](manager/manager.md) | `MemoryManager.h` | 全局内存管理器 | + +## 分配器类型对比 + +| 分配器 | 适用场景 | 特点 | +|--------|----------|------| +| `IAllocator` | 基类接口 | 定义标准分配协议 | +| `LinearAllocator` | 帧分配、临时对象 | 快速分配,只支持按顺序释放 | +| `PoolAllocator` | 同尺寸对象池 | 高效分配,消除碎片 | +| `ProxyAllocator` | 调试和统计 | 记录分配信息,跟踪内存使用 | + +## 宏定义 + +| 宏 | 描述 | +|----|------| +| `XE_ALLOC(allocator, size, ...)` | 内存分配宏 | +| `XE_FREE(allocator, ptr)` | 内存释放宏 | + +## 使用示例 + +```cpp +#include + +// 获取系统分配器 +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); + +// 创建线性分配器 +auto linearAlloc = MemoryManager::Get().CreateLinearAllocator(1024 * 1024); + +// 使用代理分配器跟踪统计 +auto proxyAlloc = MemoryManager::Get().CreateProxyAllocator("FrameData"); + +// 分配内存 +void* ptr = XE_ALLOC(linearAlloc, 1024); +XE_FREE(linearAlloc, ptr); +``` + +## 相关文档 + +- [Containers 模块](../containers/containers.md) - 使用分配器的容器 diff --git a/docs/api/memory/pool-allocator/allocate.md b/docs/api/memory/pool-allocator/allocate.md new file mode 100644 index 0000000..ce71f8d --- /dev/null +++ b/docs/api/memory/pool-allocator/allocate.md @@ -0,0 +1,38 @@ +# PoolAllocator::Allocate + +```cpp +void* Allocate(size_t size, size_t alignment = 0) override; +``` + +从内存池中分配一个空闲块。每次分配一个固定大小的块。如果 `size` 超过块大小或池中没有空闲块,返回 `nullptr`。分配操作从空闲链表头部取出一个块。 + +**参数:** +- `size` - 请求的大小,如果超过构造时指定的块大小则分配失败 +- `alignment` - 被忽略(构造时确定) + +**返回:** 分配成功返回块指针,池空返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +// 创建能容纳 1000 个整数的内存池 +PoolAllocator pool(sizeof(int), 1000, alignof(int)); + +// 分配(忽略 size 参数,只分配固定大小的块) +void* block1 = pool.Allocate(1); // 分配一块(实际大小为 sizeof(int)) +void* block2 = pool.Allocate(10000); // 也分配一块(实际大小为 sizeof(int)) + +if (block1 && block2) { + // 使用分配的内存块 + int* arr = static_cast(block1); + arr[0] = 42; +} +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 diff --git a/docs/api/memory/pool-allocator/contains.md b/docs/api/memory/pool-allocator/contains.md new file mode 100644 index 0000000..0f078e1 --- /dev/null +++ b/docs/api/memory/pool-allocator/contains.md @@ -0,0 +1,38 @@ +# PoolAllocator::Contains + +```cpp +bool Contains(void* ptr) const; +``` + +检查给定的指针是否属于此内存池的地址范围。由于池在构造时预分配连续内存,可通过指针地址区间判断所有权。此方法用于调试和内存验证。 + +**参数:** +- `ptr` - 要检查的指针 + +**返回:** 指针属于此池返回 `true`,否则返回 `false` + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +PoolAllocator pool(sizeof(int), 100); + +void* inside = pool.Allocate(); +void* outside = ::operator new(sizeof(int)); + +if (pool.Contains(inside)) { + // inside 属于此内存池,可以安全 Free +} + +if (!pool.Contains(outside)) { + // outside 不属于此池,不能调用 pool.Free() + ::operator delete(outside); +} +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 diff --git a/docs/api/memory/pool-allocator/free.md b/docs/api/memory/pool-allocator/free.md new file mode 100644 index 0000000..6e1849b --- /dev/null +++ b/docs/api/memory/pool-allocator/free.md @@ -0,0 +1,38 @@ +# PoolAllocator::Free + +```cpp +void Free(void* ptr) override; +``` + +将内存块归还到空闲链表中。如果 `ptr` 为 `nullptr` 则无效果。释放操作将块插入空闲链表头部。必须传入从此池分配的指针,传入外部指针会导致未定义行为。 + +**参数:** +- `ptr` - 指向要释放的内存块 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +PoolAllocator pool(sizeof(int), 100); + +void* block = pool.Allocate(); +if (block) { + int* num = static_cast(block); + *num = 123; + + pool.Free(block); // 归还到空闲链表 + block = nullptr; +} + +// 检查空闲块数量 +size_t freeCount = pool.GetFreeBlockCount(); +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 diff --git a/docs/api/memory/pool-allocator/get-block-size.md b/docs/api/memory/pool-allocator/get-block-size.md new file mode 100644 index 0000000..65c9cea --- /dev/null +++ b/docs/api/memory/pool-allocator/get-block-size.md @@ -0,0 +1,31 @@ +# PoolAllocator::GetBlockSize + +```cpp +size_t GetBlockSize() const; +``` + +返回内存池中每个内存块的大小。此值在构造时确定,之后保持不变。 + +**参数:** 无 + +**返回:** 每个内存块的字节大小 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +PoolAllocator pool(sizeof(int) * 100, 50); + +size_t blockSize = pool.GetBlockSize(); // 400 字节 + +void* block = pool.Allocate(); +int* arr = static_cast(block); +// arr 指向的大小为 blockSize 字节的内存块 +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 diff --git a/docs/api/memory/pool-allocator/get-free-block-count.md b/docs/api/memory/pool-allocator/get-free-block-count.md new file mode 100644 index 0000000..82ec3e9 --- /dev/null +++ b/docs/api/memory/pool-allocator/get-free-block-count.md @@ -0,0 +1,40 @@ +# PoolAllocator::GetFreeBlockCount + +```cpp +size_t GetFreeBlockCount() const; +``` + +返回当前空闲块的的数量。每次 `Allocate` 成功后减 1,每次 `Free` 后加 1。 + +**参数:** 无 + +**返回:** 当前可分配的空闲块数量 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +PoolAllocator pool(sizeof(int), 100); + +size_t initial = pool.GetFreeBlockCount(); // 100 + +void* blocks[10]; +for (int i = 0; i < 10; ++i) { + blocks[i] = pool.Allocate(); +} + +size_t after = pool.GetFreeBlockCount(); // 90 + +for (int i = 0; i < 5; ++i) { + pool.Free(blocks[i]); +} + +size_t final = pool.GetFreeBlockCount(); // 95 +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 diff --git a/docs/api/memory/pool-allocator/get-total-block-count.md b/docs/api/memory/pool-allocator/get-total-block-count.md new file mode 100644 index 0000000..45800fc --- /dev/null +++ b/docs/api/memory/pool-allocator/get-total-block-count.md @@ -0,0 +1,34 @@ +# PoolAllocator::GetTotalBlockCount + +```cpp +size_t GetTotalBlockCount() const; +``` + +返回内存池中的总块数。此值在构造时确定,之后保持不变。 + +**参数:** 无 + +**返回:** 内存池的总块数 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +PoolAllocator pool(sizeof(int), 100); + +size_t total = pool.GetTotalBlockCount(); // 100 +size_t free = pool.GetFreeBlockCount(); // 100 + +void* block = pool.Allocate(); +size_t freeAfter = pool.GetFreeBlockCount(); // 99 + +pool.Free(block); +size_t freeRestored = pool.GetFreeBlockCount(); // 100 +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 diff --git a/docs/api/memory/pool-allocator/pool-allocator.md b/docs/api/memory/pool-allocator/pool-allocator.md new file mode 100644 index 0000000..565fffe --- /dev/null +++ b/docs/api/memory/pool-allocator/pool-allocator.md @@ -0,0 +1,73 @@ +# PoolAllocator + +**命名空间**: `XCEngine::Memory` + +**类型**: `class` + +**描述**: 内存池分配器,预分配固定大小的内存块池。 + +## 概述 + +`PoolAllocator` 是一种高效固定块分配器,适合需要频繁分配和释放相同大小对象的场景,如对象池、粒子系统等。它预分配 `poolSize` 个大小为 `blockSize` 字节的内存块,通过空闲链表管理分配和回收。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `PoolAllocator` | 构造内存池分配器 | +| `~PoolAllocator` | 析构函数,释放整个内存池 | +| `Allocate` | 分配一个内存块 | +| `Free` | 释放内存块回空闲链表 | +| `Reallocate` | 不支持(始终返回 nullptr) | +| `Contains` | 检查指针是否属于此池 | +| `GetBlockSize` | 获取块大小 | +| `GetFreeBlockCount` | 获取空闲块数量 | +| `GetTotalBlockCount` | 获取总块数 | + +## 构造函数 + +```cpp +PoolAllocator(size_t blockSize, size_t poolSize, size_t alignment = 8); +~PoolAllocator() override; +``` + +构造内存池分配器,预分配 `poolSize` 个大小为 `blockSize` 字节的内存块。内存块按 `alignment` 对齐(默认 8 字节)。内部维护一个空闲块链表来管理分配。析构函数释放整个内存池。 + +**参数:** +- `blockSize` - 每个内存块的大小(字节) +- `poolSize` - 内存池中总块数 +- `alignment` - 对齐要求,默认为 8 + +**返回:** 无 + +**复杂度:** O(n),需要预分配所有块 + +**注意:** `Reallocate` 方法始终返回 `nullptr`,此分配器不支持重新分配。 + +**示例:** + +```cpp +#include + +struct Particle { + float x, y, z; + float vx, vy, vz; + float life; +}; + +// 创建一个能容纳 1000 个 Particle 的内存池,16 字节对齐 +PoolAllocator pool(sizeof(Particle), 1000, alignof(Particle)); + +size_t blockSize = pool.GetBlockSize(); // sizeof(Particle) +size_t total = pool.GetTotalBlockCount(); // 1000 +size_t free = pool.GetFreeBlockCount(); // 1000 + +// 分配和释放 +void* block = pool.Allocate(); +pool.Free(block); +``` + +## 相关文档 + +- [Memory 模块总览](../memory.md) - 返回模块总览 +- [IAllocator](../allocator/allocator.md) - 分配器接口 diff --git a/docs/api/memory/pool-allocator/reallocate.md b/docs/api/memory/pool-allocator/reallocate.md new file mode 100644 index 0000000..069730e --- /dev/null +++ b/docs/api/memory/pool-allocator/reallocate.md @@ -0,0 +1,35 @@ +# PoolAllocator::Reallocate + +```cpp +void* Reallocate(void* ptr, size_t newSize) override; +``` + +内存池分配器不支持重新分配。此方法始终返回 `nullptr`,原内存块保持不变。 + +**参数:** +- `ptr` - 不被使用 +- `newSize` - 不被使用 + +**返回:** 始终返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +#include + +PoolAllocator pool(sizeof(int), 100); +void* block = pool.Allocate(); + +// Reallocate 不支持 +void* newBlock = pool.Reallocate(block, 256); +if (!newBlock) { + // 内存池不支持重新分配 + // 原 block 仍然有效 +} +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 diff --git a/docs/api/memory/pool-allocator/~pool-allocator.md b/docs/api/memory/pool-allocator/~pool-allocator.md new file mode 100644 index 0000000..bec3636 --- /dev/null +++ b/docs/api/memory/pool-allocator/~pool-allocator.md @@ -0,0 +1,31 @@ +# PoolAllocator::~PoolAllocator + +```cpp +~PoolAllocator() override; +``` + +销毁内存池分配器,释放预分配的所有内存块。析构函数调用 `std::free` 释放整个内存池,不再需要单独释放每个块。 + +**参数:** 无 + +**返回:** 无 + +**注意:** 析构函数释放整个内存池,包括所有已分配和空闲的块。调用析构函数后,池中所有已分配出去的块也随之失效,使用这些块指针将导致未定义行为。 + +**示例:** + +```cpp +#include + +{ + PoolAllocator pool(sizeof(int), 1000); + void* block = pool.Allocate(); + // ... 使用内存块 + + pool.Free(block); // 可选:显式释放(析构时会自动释放) +} // 超出作用域时自动释放整个内存池 +``` + +## 相关文档 + +- [PoolAllocator 总览](pool-allocator.md) - 返回类总览 diff --git a/docs/api/memory/proxy-allocator/allocate.md b/docs/api/memory/proxy-allocator/allocate.md new file mode 100644 index 0000000..3973c37 --- /dev/null +++ b/docs/api/memory/proxy-allocator/allocate.md @@ -0,0 +1,37 @@ +# ProxyAllocator::Allocate + +```cpp +void* Allocate(size_t size, size_t alignment = 0) override; +``` + +分配内存并记录统计。调用转发到底层分配器,同时递增分配计数和总分配字节数,并更新峰值记录。 + +**参数:** +- `size` - 请求的字节数 +- `alignment` - 内存对齐要求 + +**返回:** 分配成功返回指针,失败返回 `nullptr` + +**复杂度:** O(1)(底层分配器复杂度 + 统计更新) + +**示例:** + +```cpp +#include +#include + +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); +ProxyAllocator proxy(sysAlloc, "TrackedAlloc"); + +void* p1 = proxy.Allocate(100); +void* p2 = proxy.Allocate(200); +void* p3 = proxy.Allocate(300, 16); + +const auto& stats = proxy.GetStats(); +printf("Total: %zu, Peak: %zu, Count: %zu\n", + stats.totalAllocated, stats.peakAllocated, stats.allocationCount); +``` + +## 相关文档 + +- [ProxyAllocator 总览](proxy-allocator.md) - 返回类总览 diff --git a/docs/api/memory/proxy-allocator/free.md b/docs/api/memory/proxy-allocator/free.md new file mode 100644 index 0000000..c4ebd3b --- /dev/null +++ b/docs/api/memory/proxy-allocator/free.md @@ -0,0 +1,42 @@ +# ProxyAllocator::Free + +```cpp +void Free(void* ptr) override; +``` + +释放内存并记录统计。调用转发到底层分配器,同时更新统计信息:递增 `totalFreed`(累加当前 `allocationCount`),并递减 `allocationCount`。 + +**注意:** `totalFreed` 累加的是每次释放时的 `allocationCount`(分配计数)而非实际字节大小。这是一个简化的实现,用于追踪释放操作次数。 + +**参数:** +- `ptr` - 指向要释放的内存块 + +**返回:** 无 + +**复杂度:** O(1)(底层释放 + 统计更新) + +**示例:** + +```cpp +#include +#include + +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); +ProxyAllocator proxy(sysAlloc, "TrackedAlloc"); + +void* p1 = proxy.Allocate(512); +void* p2 = proxy.Allocate(256); + +proxy.Free(p1); +proxy.Free(p2); + +const auto& stats = proxy.GetStats(); +// totalFreed 累加了每次释放时的 allocationCount(次数,非字节) +// allocationCount 最终为 0 +printf("Total allocated: %zu bytes, Freed count: %zu, Current count: %zu\n", + stats.totalAllocated, stats.totalFreed, stats.allocationCount); +``` + +## 相关文档 + +- [ProxyAllocator 总览](proxy-allocator.md) - 返回类总览 diff --git a/docs/api/memory/proxy-allocator/get-stats.md b/docs/api/memory/proxy-allocator/get-stats.md new file mode 100644 index 0000000..6fab8a5 --- /dev/null +++ b/docs/api/memory/proxy-allocator/get-stats.md @@ -0,0 +1,40 @@ +# ProxyAllocator::GetStats + +```cpp +const Stats& GetStats() const; +``` + +返回详细的统计信息结构体引用。包含累计分配、累计释放、峰值分配、分配次数和额外开销。返回 const 引用,无锁开销(内部已有互斥保护)。 + +**参数:** 无 + +**返回:** Stats 结构体 const 引用 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include +#include + +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); +ProxyAllocator proxy(sysAlloc, "FrameData"); + +proxy.Allocate(1024); +proxy.Allocate(512); +proxy.Free(proxy.Allocate(256)); + +const ProxyAllocator::Stats& stats = proxy.GetStats(); +printf("Total allocated: %zu bytes\n", stats.totalAllocated); +printf("Total freed: %zu times\n", stats.totalFreed); +printf("Peak allocated: %zu bytes\n", stats.peakAllocated); +printf("Allocation count: %zu\n", stats.allocationCount); +printf("Memory overhead: %zu bytes\n", stats.memoryOverhead); +printf("Current in use: %zu bytes\n", + stats.totalAllocated - stats.allocationCount * sizeof(/* typical block */ size_t)); +``` + +## 相关文档 + +- [ProxyAllocator 总览](proxy-allocator.md) - 返回类总览 diff --git a/docs/api/memory/proxy-allocator/proxy-allocator.md b/docs/api/memory/proxy-allocator/proxy-allocator.md new file mode 100644 index 0000000..40f6736 --- /dev/null +++ b/docs/api/memory/proxy-allocator/proxy-allocator.md @@ -0,0 +1,61 @@ +# ProxyAllocator + +**命名空间**: `XCEngine::Memory` + +**类型**: `class` + +**描述**: 代理分配器,用于统计和跟踪底层分配器的分配情况。 + +## 概述 + +`ProxyAllocator` 包装一个底层分配器,转发所有分配请求,同时记录详细的统计信息。它线程安全(使用互斥锁保护统计数据),适合需要监控内存使用的场景。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `ProxyAllocator` | 构造代理分配器 | +| `~ProxyAllocator` | 析构函数 | +| `Allocate` | 分配内存并记录统计 | +| `Free` | 释放内存并记录统计 | +| `Reallocate` | 转发到底层分配器 | +| `GetStats` | 获取详细统计信息 | + +## 构造函数 + +```cpp +ProxyAllocator(IAllocator* underlying, const char* name); +``` + +构造一个代理分配器,包装底层分配器并记录分配统计。所有 `Allocate`、`Free`、`Reallocate` 调用都会被转发到底层分配器,同时记录统计信息。名称用于日志和报告。 + +**参数:** +- `underlying` - 被包装的底层分配器,不能为 `nullptr` +- `name` - 代理分配器的名称字符串 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +#include +#include + +MemoryManager::Get().Initialize(); + +// 使用系统分配器作为底层 +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); +ProxyAllocator proxy(sysAlloc, "TempAllocations"); + +// 通过代理分配 +void* ptr = proxy.Allocate(1024); +proxy.Free(ptr); +``` + +## 相关文档 + +- [Memory 模块总览](../memory.md) - 返回模块总览 +- [IAllocator](../allocator/allocator.md) - 分配器接口 +- [MemoryManager](../manager/manager.md) - 内存管理器 diff --git a/docs/api/memory/proxy-allocator/reallocate.md b/docs/api/memory/proxy-allocator/reallocate.md new file mode 100644 index 0000000..6d1f0e8 --- /dev/null +++ b/docs/api/memory/proxy-allocator/reallocate.md @@ -0,0 +1,38 @@ +# ProxyAllocator::Reallocate + +```cpp +void* Reallocate(void* ptr, size_t newSize) override; +``` + +重新分配内存。调用转发到底层分配器,不记录额外统计信息(底层分配器的返回值直接返回)。此方法线程安全,内部使用互斥锁保护。 + +**参数:** +- `ptr` - 现有内存块指针 +- `newSize` - 新的字节大小 + +**返回:** 成功返回新指针,失败返回 `nullptr`(由底层分配器决定) + +**复杂度:** O(n)(底层分配器 + 数据复制) + +**示例:** + +```cpp +#include +#include + +IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); +ProxyAllocator proxy(sysAlloc, "TrackedAlloc"); + +void* p1 = proxy.Allocate(128); +void* p2 = proxy.Reallocate(p1, 256); + +if (p2) { + // 重新分配成功 +} else { + // 失败,p1 仍然有效 +} +``` + +## 相关文档 + +- [ProxyAllocator 总览](proxy-allocator.md) - 返回类总览 diff --git a/docs/api/memory/proxy-allocator/~proxy-allocator.md b/docs/api/memory/proxy-allocator/~proxy-allocator.md new file mode 100644 index 0000000..68846e7 --- /dev/null +++ b/docs/api/memory/proxy-allocator/~proxy-allocator.md @@ -0,0 +1,37 @@ +# ProxyAllocator::~ProxyAllocator + +```cpp +~ProxyAllocator() override; +``` + +销毁代理分配器。此析构函数不释放底层分配器,只清理代理分配器自身的统计信息(互斥锁等)。底层分配器由创建者负责管理。 + +**参数:** 无 + +**返回:** 无 + +**注意:** 析构函数不释放底层分配器。如果需要释放底层分配器,应先调用 `Shutdown` 或显式销毁底层分配器。 + +**示例:** + +```cpp +#include +#include + +{ + MemoryManager::Get().Initialize(); + IAllocator* sysAlloc = MemoryManager::Get().GetSystemAllocator(); + + auto proxy = MemoryManager::Get().CreateProxyAllocator("TrackedAlloc"); + proxy->Allocate(1024); + + // proxy 超出作用域时自动销毁 + // 底层 sysAlloc 仍有效 + + MemoryManager::Get().Shutdown(); +} +``` + +## 相关文档 + +- [ProxyAllocator 总览](proxy-allocator.md) - 返回类总览 diff --git a/docs/api/resources/asyncloader/asyncloader.md b/docs/api/resources/asyncloader/asyncloader.md new file mode 100644 index 0000000..ed1955d --- /dev/null +++ b/docs/api/resources/asyncloader/asyncloader.md @@ -0,0 +1,107 @@ +# AsyncLoader + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` (singleton) + +**描述**: 异步资源加载器单例,负责多线程后台资源加载和完成回调调度。 + +## 概述 + +`AsyncLoader` 是 XCEngine 的后台异步加载系统。它使用独立工作线程从磁盘加载资源,并在加载完成后通过回调通知调用者。它维护待处理队列和完成队列,通过双缓冲机制实现无锁的线程安全操作。 + +## 单例访问 + +| 方法 | 描述 | +|------|------| +| `static AsyncLoader& Get()` | 获取单例实例 | + +## LoadRequest 结构体 + +异步加载请求结构体。 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `path` | `Containers::String` | 资源路径 | +| `type` | `ResourceType` | 资源类型 | +| `callback` | `std::function` | 加载完成回调函数 | +| `settings` | `ImportSettings*` | 导入设置(可为 nullptr) | +| `requestId` | `Core::uint64` | 请求唯一标识符 | + +### 构造方法 + +| 方法 | 描述 | +|------|------| +| `LoadRequest()` | 默认构造 | +| `LoadRequest(const Containers::String& p, ResourceType t, std::function cb, ImportSettings* s = nullptr)` | 从参数构造 | +| `LoadRequest(LoadRequest&& other) noexcept` | 移动构造 | +| `LoadRequest(const LoadRequest&) = default` | 拷贝构造 | + +### 赋值 + +| 方法 | 描述 | +|------|------| +| `LoadRequest& operator=(LoadRequest&& other) noexcept` | 移动赋值 | +| `LoadRequest& operator=(const LoadRequest&) = default` | 拷贝赋值 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `void Initialize(Core::uint32 workerThreadCount = 2)` | 初始化异步加载器,创建工作线程 | +| `void Shutdown()` | 关闭异步加载器,等待所有挂起任务完成 | +| `void Submit(const Containers::String& path, ResourceType type, std::function callback)` | 提交异步加载请求 | +| `void Submit(const Containers::String& path, ResourceType type, ImportSettings* settings, std::function callback)` | 带设置的异步加载请求 | +| `void Update()` | 更新函数,在主线程调用,处理完成的加载请求 | +| `bool IsLoading() const` | 是否有正在加载的资源 | +| `Core::uint32 GetPendingCount() const` | 获取待处理加载请求数量 | +| `float GetProgress() const` | 获取整体加载进度(0.0f ~ 1.0f) | +| `void CancelAll()` | 取消所有待处理的加载请求 | +| `void Cancel(Core::uint64 requestId)` | 取消指定 ID 的加载请求 | + +## 实现说明 + +**注意**: 当前 `AsyncLoader` 的实现为部分完成状态(stub): +- `Initialize()` 工作线程数参数被忽略 +- `Submit()` 仅将请求加入队列,不进行实际异步加载 +- `Update()` 不执行实际加载,直接调用回调返回成功 +- `QueueCompleted()` 和 `Cancel()` 为空实现 + +## 使用示例 + +```cpp +// 初始化(使用 4 个工作线程) +AsyncLoader::Get().Initialize(4); + +// 提交多个异步加载请求 +AsyncLoader::Get().Submit("textures/player.png", ResourceType::Texture, + [](LoadResult result) { + if (result.success) { + ResourceHandle tex(result.resource); + printf("Texture loaded: %s\n", tex->GetPath().CStr()); + } + }); + +AsyncLoader::Get().Submit("models/player.fbx", ResourceType::Mesh, + [](LoadResult result) { + if (result.success) { + ResourceHandle mesh(result.resource); + printf("Mesh loaded: %s\n", mesh->GetPath().CStr()); + } + }); + +// 在主循环中调用 Update 处理完成回调 +while (AsyncLoader::Get().IsLoading()) { + AsyncLoader::Get().Update(); // 在主线程分发回调 + // 其他渲染逻辑... +} + +// 关闭 +AsyncLoader::Get().Shutdown(); +``` + +## 相关文档 + +- [ResourceManager](../resourcemanager/resourcemanager.md) - 资源管理器 +- [IResourceLoader](../iloader/iloader.md) - 资源加载器接口 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/asyncloader/cancelall.md b/docs/api/resources/asyncloader/cancelall.md new file mode 100644 index 0000000..8aa163d --- /dev/null +++ b/docs/api/resources/asyncloader/cancelall.md @@ -0,0 +1,26 @@ +# AsyncLoader::CancelAll + +```cpp +void CancelAll() +``` + +取消所有待处理的加载请求。清空待处理队列,不会触发任何回调。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +// 场景切换时取消所有加载请求 +void OnSceneChange() { + AsyncLoader::Get().CancelAll(); +} +``` + +## 相关文档 + +- [AsyncLoader 总览](asyncloader.md) - 返回类总览 diff --git a/docs/api/resources/asyncloader/getprogress.md b/docs/api/resources/asyncloader/getprogress.md new file mode 100644 index 0000000..3a8cc2b --- /dev/null +++ b/docs/api/resources/asyncloader/getprogress.md @@ -0,0 +1,24 @@ +# AsyncLoader::GetProgress + +```cpp +float GetProgress() const +``` + +获取整体加载进度。返回已完成加载数与总请求数的比值,范围 0.0f ~ 1.0f。 + +**参数:** 无 + +**返回:** 加载进度(0.0f ~ 1.0f) + +**复杂度:** O(1) + +**示例:** + +```cpp +float progress = AsyncLoader::Get().GetProgress(); +printf("Loading: %.1f%%\n", progress * 100.0f); +``` + +## 相关文档 + +- [AsyncLoader 总览](asyncloader.md) - 返回类总览 diff --git a/docs/api/resources/asyncloader/submit.md b/docs/api/resources/asyncloader/submit.md new file mode 100644 index 0000000..e05f329 --- /dev/null +++ b/docs/api/resources/asyncloader/submit.md @@ -0,0 +1,35 @@ +# AsyncLoader::Submit + +```cpp +void Submit(const Containers::String& path, ResourceType type, + std::function callback) +void Submit(const Containers::String& path, ResourceType type, ImportSettings* settings, + std::function callback) +``` + +提交异步加载请求。将请求加入待处理队列,由工作线程在后台执行加载。 + +**参数:** +- `path` - 资源路径 +- `type` - 资源类型 +- `settings` - 导入设置(可为 nullptr) +- `callback` - 加载完成回调 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +AsyncLoader::Get().Submit("textures/player.png", ResourceType::Texture, + [](LoadResult result) { + if (result.success) { + ResourceHandle tex(result.resource); + } + }); +``` + +## 相关文档 + +- [AsyncLoader 总览](asyncloader.md) - 返回类总览 diff --git a/docs/api/resources/asyncloader/update.md b/docs/api/resources/asyncloader/update.md new file mode 100644 index 0000000..946f703 --- /dev/null +++ b/docs/api/resources/asyncloader/update.md @@ -0,0 +1,27 @@ +# AsyncLoader::Update + +```cpp +void Update() +``` + +更新函数,在主线程调用。处理完成的加载请求,将结果从完成队列取出并在主线程执行回调。必须在主线程调用以确保线程安全。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n),n 为完成队列中的请求数 + +**示例:** + +```cpp +// 在主循环中调用 +while (running) { + AsyncLoader::Get().Update(); // 分发完成的加载回调 + RenderFrame(); +} +``` + +## 相关文档 + +- [AsyncLoader 总览](asyncloader.md) - 返回类总览 diff --git a/docs/api/resources/audioclip/audioclip.md b/docs/api/resources/audioclip/audioclip.md new file mode 100644 index 0000000..ada1c2b --- /dev/null +++ b/docs/api/resources/audioclip/audioclip.md @@ -0,0 +1,139 @@ +# AudioClip + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` + +**描述**: 音频片段资源类,管理音频样本数据、格式信息和播放参数。 + +## 概述 + +`AudioClip` 是 XCEngine 中的音频资源类,继承自 `IResource`。它管理音频的原始样本数据、采样率、通道数、位深度、时长、格式类型和播放参数。 + +## 头文件 + +```cpp +#include +``` + +## 枚举类型 + +### AudioFormat + +音频格式枚举。 + +| 值 | 描述 | +|----|------| +| `Unknown` | 未知格式 | +| `WAV` | WAV 格式 | +| `OGG` | OGG Vorbis 格式 | +| `MP3` | MP3 格式 | +| `FLAC` | FLAC 无损格式 | + +### AudioType + +音频类型枚举。 + +| 值 | 描述 | +|----|------| +| `SoundEffect` | 音效 | +| `Music` | 音乐 | +| `Voice` | 语音 | +| `Ambient` | 环境音 | + +## 公共方法 + +### 基础属性 + +| 方法 | 描述 | +|------|------| +| `ResourceType GetType() const` | 返回 `ResourceType::AudioClip` | +| `const Containers::String& GetName() const` | 获取音频名称 | +| `const Containers::String& GetPath() const` | 获取音频路径 | +| `ResourceGUID GetGUID() const` | 获取全局唯一标识符 | +| `bool IsValid() const` | 检查音频是否有效 | +| `size_t GetMemorySize() const` | 获取内存大小 | +| `void Release()` | 释放音频引用 | + +### 音频数据 + +| 方法 | 描述 | +|------|------| +| `void SetAudioData(const Containers::Array& data)` | 设置音频数据(根据采样率、通道数、位深度自动计算时长) | +| `const Containers::Array& GetAudioData() const` | 获取音频数据指针 | + +## 实现说明 + +**注意**: +- `AudioLoader::Load()` 加载 WAV 文件时仅设置格式,不解析 WAV 头信息来设置采样率、通道数和位深度。这些字段需要手动设置或通过 `SetAudioData()` 的自动计算(需先设置 `m_sampleRate`、`m_channels`、`m_bitsPerSample`)。 +- `AudioLoader::ParseWAVData()` 为 stub,始终返回 true。 +- `AudioLoader::DetectAudioFormat()` 不检测 AIFF/AIF 格式的文件头,仅依赖扩展名判断。 + +### 音频参数 + +| 方法 | 描述 | +|------|------| +| `void SetSampleRate(Core::uint32 rate)` | 设置采样率(Hz) | +| `Core::uint32 GetSampleRate() const` | 获取采样率 | +| `void SetChannels(Core::uint32 channels)` | 设置通道数(1=单声道, 2=立体声) | +| `Core::uint32 GetChannels() const` | 获取通道数 | +| `void SetBitsPerSample(Core::uint32 bits)` | 设置位深度(8/16/24/32) | +| `Core::uint32 GetBitsPerSample() const` | 获取位深度 | +| `void SetDuration(float seconds)` | 设置时长(秒) | +| `float GetDuration() const` | 获取时长(秒) | + +### 格式与类型 + +| 方法 | 描述 | +|------|------| +| `void SetAudioFormat(AudioFormat format)` | 设置音频格式 | +| `AudioFormat GetAudioFormat() const` | 获取音频格式 | +| `void SetAudioType(AudioType type)` | 设置音频类型 | +| `AudioType GetAudioType() const` | 获取音频类型 | + +### 3D 和循环 + +| 方法 | 描述 | +|------|------| +| `void SetIs3D(bool is3D)` | 设置是否为 3D 音频 | +| `bool Is3D() const` | 检查是否为 3D 音频 | +| `void SetLoop(bool loop)` | 设置是否循环播放 | +| `bool IsLoop() const` | 检查是否循环播放 | + +### RHI 资源 + +| 方法 | 描述 | +|------|------| +| `class IRHIAudioBuffer* GetRHIResource() const` | 获取 RHI 音频缓冲区 | +| `void SetRHIResource(class IRHIAudioBuffer* resource)` | 设置 RHI 音频缓冲区 | + +## 使用示例 + +```cpp +// 加载音频 +ResourceHandle sfx = ResourceManager::Get().Load("sounds/explosion.wav"); +ResourceHandle music = ResourceManager::Get().Load("music/background.ogg"); + +// 设置参数 +sfx->SetAudioType(AudioType::SoundEffect); +sfx->SetSampleRate(44100); +sfx->SetChannels(2); +sfx->SetBitsPerSample(16); +sfx->SetDuration(1.5f); +sfx->SetLoop(false); + +// 3D 音频 +sfx->SetIs3D(false); +music->SetIs3D(false); + +// 获取信息 +uint32_t sampleRate = sfx->GetSampleRate(); +float duration = sfx->GetDuration(); +bool loop = sfx->IsLoop(); +``` + +## 相关文档 + +- [IResource](../iresource/iresource.md) - 资源基类 +- [ResourceManager](../resourcemanager/resourcemanager.md) - 资源管理器 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/audioclip/setaudiodata.md b/docs/api/resources/audioclip/setaudiodata.md new file mode 100644 index 0000000..e7d147f --- /dev/null +++ b/docs/api/resources/audioclip/setaudiodata.md @@ -0,0 +1,29 @@ +# AudioClip::SetAudioData + +```cpp +void SetAudioData(const Containers::Array& data) +``` + +设置音频原始样本数据。 + +**参数:** +- `data` - 音频数据字节数组 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +auto wavData = ResourceFileSystem::Get().ReadResource("sounds/explosion.wav"); +AudioClip* clip = new AudioClip(); +clip->SetAudioData(wavData); +clip->SetSampleRate(44100); +clip->SetChannels(2); +clip->SetBitsPerSample(16); +``` + +## 相关文档 + +- [AudioClip 总览](audioclip.md) - 返回类总览 diff --git a/docs/api/resources/dependencygraph/adddependency.md b/docs/api/resources/dependencygraph/adddependency.md new file mode 100644 index 0000000..301eccb --- /dev/null +++ b/docs/api/resources/dependencygraph/adddependency.md @@ -0,0 +1,27 @@ +# ResourceDependencyGraph::AddDependency + +```cpp +void AddDependency(ResourceGUID owner, ResourceGUID dependency) +``` + +添加资源依赖关系。表示 `owner` 资源依赖 `dependency` 资源。依赖关系是单向的。 + +**参数:** +- `owner` - 拥有依赖关系的主体资源 +- `dependency` - 被依赖的资源 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +// Material 依赖 Texture 和 Shader +graph.AddDependency(materialGuid, textureGuid); +graph.AddDependency(materialGuid, shaderGuid); +``` + +## 相关文档 + +- [ResourceDependencyGraph 总览](dependencygraph.md) - 返回类总览 diff --git a/docs/api/resources/dependencygraph/addnode.md b/docs/api/resources/dependencygraph/addnode.md new file mode 100644 index 0000000..a8bd4ac --- /dev/null +++ b/docs/api/resources/dependencygraph/addnode.md @@ -0,0 +1,27 @@ +# ResourceDependencyGraph::AddNode + +```cpp +void AddNode(ResourceGUID guid, ResourceType type) +``` + +向依赖图中添加一个新节点。如果节点已存在则忽略。 + +**参数:** +- `guid` - 资源的全局唯一标识符 +- `type` - 资源类型 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +ResourceDependencyGraph graph; +graph.AddNode(textureGuid, ResourceType::Texture); +graph.AddNode(materialGuid, ResourceType::Material); +``` + +## 相关文档 + +- [ResourceDependencyGraph 总览](dependencygraph.md) - 返回类总览 diff --git a/docs/api/resources/dependencygraph/dependencygraph.md b/docs/api/resources/dependencygraph/dependencygraph.md new file mode 100644 index 0000000..932fbbf --- /dev/null +++ b/docs/api/resources/dependencygraph/dependencygraph.md @@ -0,0 +1,88 @@ +# ResourceDependencyGraph + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` + +**描述**: 资源依赖图管理器,负责跟踪资源之间的依赖关系、引用计数和拓扑排序。 + +## 概述 + +`ResourceDependencyGraph` 维护了所有资源之间的依赖关系图。它支持添加/移除依赖节点、查询依赖关系、循环依赖检测、拓扑排序(用于正确的加载/卸载顺序)等功能。 + +## DependencyNode 结构体 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `guid` | `ResourceGUID` | 资源全局唯一标识符 | +| `type` | `ResourceType` | 资源类型 | +| `dependencies` | `Containers::Array` | 此资源依赖的其他资源 | +| `dependents` | `Containers::Array` | 依赖此资源的其他资源 | +| `refCount` | `Core::uint32` | 引用计数 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `void AddNode(ResourceGUID guid, ResourceType type)` | 添加依赖节点 | +| `void RemoveNode(ResourceGUID guid)` | 移除依赖节点 | +| `bool HasNode(ResourceGUID guid) const` | 检查节点是否存在 | +| `void AddDependency(ResourceGUID owner, ResourceGUID dependency)` | 添加依赖关系(A 依赖 B) | +| `void RemoveDependency(ResourceGUID owner, ResourceGUID dependency)` | 移除依赖关系 | +| `Containers::Array GetDependencies(ResourceGUID guid) const` | 获取指定资源的直接依赖列表 | +| `Containers::Array GetDependents(ResourceGUID guid) const` | 获取依赖指定资源的所有资源列表 | +| `Containers::Array GetAllDependencies(ResourceGUID guid) const` | 获取所有递归依赖(包括传递依赖) | +| `void IncrementRefCount(ResourceGUID guid)` | 增加引用计数 | +| `void DecrementRefCount(ResourceGUID guid)` | 减少引用计数 | +| `Core::uint32 GetRefCount(ResourceGUID guid) const` | 获取引用计数 | +| `bool HasCircularDependency(ResourceGUID guid, Containers::Array& outCycle) const` | 检测是否存在循环依赖 | +| `Containers::Array TopologicalSort() const` | 拓扑排序(当前返回空数组 - stub) | +| `bool Unload(ResourceGUID guid)` | 安全卸载(考虑依赖关系) | +| `void Clear()` | 清空所有节点和依赖关系 | + +## 实现说明 + +**注意**: `TopologicalSort()` 当前为 stub,返回空数组。 + +## 使用示例 + +```cpp +ResourceDependencyGraph graph; + +// 添加节点 +graph.AddNode(textureGuid, ResourceType::Texture); +graph.AddNode(materialGuid, ResourceType::Material); +graph.AddNode(shaderGuid, ResourceType::Shader); + +// 设置依赖关系:Material 依赖 Texture 和 Shader +graph.AddDependency(materialGuid, textureGuid); +graph.AddDependency(materialGuid, shaderGuid); + +// 查询依赖 +auto deps = graph.GetDependencies(materialGuid); +// deps 包含 textureGuid 和 shaderGuid + +// 查询被依赖者 +auto dependents = graph.GetDependents(textureGuid); +// dependents 包含 materialGuid + +// 拓扑排序(正确的加载顺序) +auto loadOrder = graph.TopologicalSort(); +// loadOrder 保证依赖在目标之前加载 + +// 循环依赖检测 +Containers::Array cycle; +if (graph.HasCircularDependency(guid, cycle)) { + printf("Circular dependency detected!"); +} + +// 引用计数 +graph.IncrementRefCount(guid); +graph.DecrementRefCount(guid); +``` + +## 相关文档 + +- [ResourceManager](../resourcemanager/resourcemanager.md) - 资源管理器 +- [ResourceHandle](../resourcehandle/resourcehandle.md) - 资源句柄 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/dependencygraph/getdependencies.md b/docs/api/resources/dependencygraph/getdependencies.md new file mode 100644 index 0000000..733fdd2 --- /dev/null +++ b/docs/api/resources/dependencygraph/getdependencies.md @@ -0,0 +1,25 @@ +# ResourceDependencyGraph::GetDependencies + +```cpp +Containers::Array GetDependencies(ResourceGUID guid) const +``` + +获取指定资源直接依赖的所有资源列表。不包含传递依赖。 + +**参数:** +- `guid` - 资源全局唯一标识符 + +**返回:** 直接依赖的 GUID 数组 + +**复杂度:** O(k),k 为直接依赖数量 + +**示例:** + +```cpp +auto deps = graph.GetDependencies(materialGuid); +// 返回 Material 直接依赖的资源(Texture、Shader 等) +``` + +## 相关文档 + +- [ResourceDependencyGraph 总览](dependencygraph.md) - 返回类总览 diff --git a/docs/api/resources/dependencygraph/hascirculardependency.md b/docs/api/resources/dependencygraph/hascirculardependency.md new file mode 100644 index 0000000..b358cd7 --- /dev/null +++ b/docs/api/resources/dependencygraph/hascirculardependency.md @@ -0,0 +1,31 @@ +# ResourceDependencyGraph::HasCircularDependency + +```cpp +bool HasCircularDependency(ResourceGUID guid, Containers::Array& outCycle) const +``` + +检测是否存在以指定节点为起点的循环依赖。使用 DFS 遍历依赖图,检测回路。 + +**参数:** +- `guid` - 起始节点 +- `outCycle` - 输出参数,检测到的循环路径(包含形成环的节点 GUID) + +**返回:** 如果存在循环依赖则返回 true,否则返回 false + +**复杂度:** O(n + e) + +**示例:** + +```cpp +Containers::Array cycle; +if (graph.HasCircularDependency(guid, cycle)) { + printf("Circular dependency detected: "); + for (const auto& g : cycle) { + printf("%llu ", g.value); + } +} +``` + +## 相关文档 + +- [ResourceDependencyGraph 总览](dependencygraph.md) - 返回类总览 diff --git a/docs/api/resources/dependencygraph/topologicalsort.md b/docs/api/resources/dependencygraph/topologicalsort.md new file mode 100644 index 0000000..9a539ad --- /dev/null +++ b/docs/api/resources/dependencygraph/topologicalsort.md @@ -0,0 +1,28 @@ +# ResourceDependencyGraph::TopologicalSort + +```cpp +Containers::Array TopologicalSort() const +``` + +拓扑排序。按依赖顺序返回所有节点,确保被依赖的资源排在依赖者之前。用于确定正确的加载和卸载顺序。 + +**参数:** 无 + +**返回:** 按依赖顺序排序的 GUID 数组 + +**复杂度:** O(n + e),n 为节点数,e 为边数 + +**示例:** + +```cpp +auto loadOrder = graph.TopologicalSort(); +// loadOrder[0] 是最底层依赖(如 Texture) +// loadOrder[last] 是最顶层资源(如 Material) +for (const auto& guid : loadOrder) { + ResourceManager::Get().Load(guid); +} +``` + +## 相关文档 + +- [ResourceDependencyGraph 总览](dependencygraph.md) - 返回类总览 diff --git a/docs/api/resources/filearchive/filearchive.md b/docs/api/resources/filearchive/filearchive.md new file mode 100644 index 0000000..7138ebb --- /dev/null +++ b/docs/api/resources/filearchive/filearchive.md @@ -0,0 +1,84 @@ +# FileArchive + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` (extends IArchive) + +**描述**: 文件归档封装类,用于读取归档包(如 .pak、.zip)中的资源文件。 + +## 概述 + +`FileArchive` 实现了 `IArchive` 接口,提供从单个归档包文件中读取资源的功能。它维护已打开归档的路径和有效性状态。 + +## 头文件 + +```cpp +#include +``` + +## 继承关系 + +``` +IArchive +└── FileArchive +``` + +## 公共方法 + +### 构造与析构 + +| 方法 | 描述 | +|------|------| +| `FileArchive()` | 默认构造 | +| `~FileArchive()` | 析构函数,关闭归档 | + +### IArchive 接口实现 + +| 方法 | 描述 | +|------|------| +| `bool Open(const Containers::String& path) override` | 打开归档文件 | +| `void Close() override` | 关闭归档文件 | +| `bool Read(const Containers::String& fileName, void* buffer, size_t size, size_t offset) const override` | 从归档中读取文件数据 | +| `size_t GetSize(const Containers::String& fileName) const override` | 获取归档内文件大小 | +| `bool Exists(const Containers::String& fileName) const override` | 检查文件是否存在于归档中 | +| `void Enumerate(const Containers::String& pattern, Containers::Array& outFiles) const override` | 枚举归档内匹配的文件(当前为 stub) | +| `bool IsValid() const override` | 检查归档是否有效 | + +## 实现说明 + +**注意**: `Enumerate()` 当前为 stub,仅清空输出数组。 + +### 访问器 + +| 方法 | 描述 | +|------|------| +| `const Containers::String& GetPath() const` | 获取归档文件路径 | + +## 使用示例 + +```cpp +FileArchive archive; +if (archive.Open("data/resources.pak")) { + // 检查文件是否存在 + if (archive.Exists("textures/player.png")) { + // 获取文件大小 + size_t size = archive.GetSize("textures/player.png"); + + // 读取文件内容 + Containers::Array buffer(size); + archive.Read("textures/player.png", buffer.Data(), size, 0); + } + + // 枚举文件 + Containers::Array files; + archive.Enumerate("textures/*.png", files); + + archive.Close(); +} +``` + +## 相关文档 + +- [IArchive](../filesystem/filesystem.md) - 归档接口 +- [ResourceFileSystem](../filesystem/filesystem.md) - 资源文件系统 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/filesystem/exists.md b/docs/api/resources/filesystem/exists.md new file mode 100644 index 0000000..aedf818 --- /dev/null +++ b/docs/api/resources/filesystem/exists.md @@ -0,0 +1,26 @@ +# ResourceFileSystem::Exists + +```cpp +bool Exists(const Containers::String& relativePath) const +``` + +检查资源文件是否存在。优先在归档包中查找,其次在目录中查找。 + +**参数:** +- `relativePath` - 资源相对路径 + +**返回:** 如果存在则返回 true + +**复杂度:** O(1) + +**示例:** + +```cpp +if (ResourceFileSystem::Get().Exists("shaders/default.vert")) { + // 文件存在... +} +``` + +## 相关文档 + +- [ResourceFileSystem 总览](filesystem.md) - 返回类总览 diff --git a/docs/api/resources/filesystem/filesystem.md b/docs/api/resources/filesystem/filesystem.md new file mode 100644 index 0000000..29208ad --- /dev/null +++ b/docs/api/resources/filesystem/filesystem.md @@ -0,0 +1,104 @@ +# ResourceFileSystem + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` + +**描述**: 资源文件系统,负责资源文件的查找、读取和虚拟文件系统(支持目录和归档包)管理。 + +## 概述 + +`ResourceFileSystem` 实现了虚拟资源文件系统,支持从多个目录和归档包(如 `.zip`、`.pak`)中查找和读取资源。它通过 `IArchive` 接口支持不同的归档格式,并提供资源信息缓存。 + +## 单例访问 + +| 方法 | 描述 | +|------|------| +| `static ResourceFileSystem& Get()` | 获取单例实例 | + +## IArchive 接口 + +抽象归档接口,用于封装单个归档包或目录的读取操作。 + +### 公共方法 + +| 方法 | 描述 | +|------|------| +| `virtual bool Open(const Containers::String& path)` | 打开归档 | +| `virtual void Close()` | 关闭归档 | +| `virtual bool Read(const Containers::String& fileName, void* buffer, size_t size, size_t offset) const` | 从归档中读取文件 | +| `virtual size_t GetSize(const Containers::String& fileName) const` | 获取文件大小 | +| `virtual bool Exists(const Containers::String& fileName) const` | 检查文件是否存在 | +| `virtual void Enumerate(const Containers::String& pattern, Containers::Array& outFiles) const` | 枚举匹配的文件 | +| `virtual bool IsValid() const` | 是否有效 | + +## ResourceInfo 结构体 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `path` | `Containers::String` | 资源相对路径 | +| `size` | `size_t` | 文件大小(字节) | +| `modifiedTime` | `Core::uint64` | 修改时间戳 | +| `inArchive` | `bool` | 是否在归档包中 | +| `archivePath` | `Containers::String` | 所属归档路径 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `void Initialize(const Containers::String& rootPath)` | 初始化,设置资源根目录 | +| `void Shutdown()` | 关闭,释放所有归档 | +| `bool AddArchive(const Containers::String& archivePath)` | 添加归档包(优先查找) | +| `bool AddDirectory(const Containers::String& directoryPath)` | 添加资源目录 | +| `void RemoveArchive(const Containers::String& archivePath)` | 移除归档包 | +| `bool FindResource(const Containers::String& relativePath, Containers::String& outAbsolutePath) const` | 查找资源的绝对路径 | +| `bool Exists(const Containers::String& relativePath) const` | 检查资源是否存在 | +| `Containers::Array ReadResource(const Containers::String& relativePath) const` | 读取资源文件内容(字节数组) | +| `bool GetResourceInfo(const Containers::String& relativePath, ResourceInfo& outInfo) const` | 获取资源信息(部分字段可能未填充) | +| `void EnumerateResources(const Containers::String& pattern, Containers::Array& outResources) const` | 枚举匹配的资源(当前为 stub,仅清空输出) | + +## 实现说明 + +**注意**: 当前 `GetResourceInfo()` 不填充 `modifiedTime` 字段,`EnumerateResources()` 为 stub 实现。 + +## 使用示例 + +```cpp +// 初始化资源文件系统 +ResourceFileSystem::Get().Initialize("resources/"); + +// 添加归档包(优先于目录) +ResourceFileSystem::Get().AddArchive("data/resources.pak"); + +// 添加额外资源目录 +ResourceFileSystem::Get().AddDirectory("user_content/"); + +// 检查资源是否存在 +if (ResourceFileSystem::Get().Exists("textures/player.png")) { + // 读取资源 + auto data = ResourceFileSystem::Get().ReadResource("textures/player.png"); + // 使用数据... +} + +// 获取资源信息 +ResourceInfo info; +if (ResourceFileSystem::Get().GetResourceInfo("shaders/default.vert", info)) { + printf("Size: %zu, InArchive: %s\n", info.size, info.inArchive ? "yes" : "no"); +} + +// 枚举资源 +Containers::Array textures; +ResourceFileSystem::Get().EnumerateResources("textures/*.png", textures); +for (const auto& tex : textures) { + printf("Found: %s\n", tex.path.CStr()); +} + +// 关闭 +ResourceFileSystem::Get().Shutdown(); +``` + +## 相关文档 + +- [ResourceManager](../resourcemanager/resourcemanager.md) - 资源管理器 +- [IResourceLoader](../iloader/iloader.md) - 资源加载器 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/filesystem/initialize.md b/docs/api/resources/filesystem/initialize.md new file mode 100644 index 0000000..6ac2d76 --- /dev/null +++ b/docs/api/resources/filesystem/initialize.md @@ -0,0 +1,24 @@ +# ResourceFileSystem::Initialize + +```cpp +void Initialize(const Containers::String& rootPath) +``` + +初始化资源文件系统。设置资源根目录,准备虚拟文件系统。 + +**参数:** +- `rootPath` - 资源根目录路径 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +ResourceFileSystem::Get().Initialize("resources/"); +``` + +## 相关文档 + +- [ResourceFileSystem 总览](filesystem.md) - 返回类总览 diff --git a/docs/api/resources/filesystem/readresource.md b/docs/api/resources/filesystem/readresource.md new file mode 100644 index 0000000..fd9e051 --- /dev/null +++ b/docs/api/resources/filesystem/readresource.md @@ -0,0 +1,27 @@ +# ResourceFileSystem::ReadResource + +```cpp +Containers::Array ReadResource(const Containers::String& relativePath) const +``` + +读取资源文件内容。优先从归档包中读取,其次从目录中查找。 + +**参数:** +- `relativePath` - 资源相对路径 + +**返回:** 文件内容的字节数组,读取失败返回空数组 + +**复杂度:** O(n),n 为文件大小 + +**示例:** + +```cpp +auto data = ResourceFileSystem::Get().ReadResource("textures/player.png"); +if (!data.Empty()) { + // 使用数据... +} +``` + +## 相关文档 + +- [ResourceFileSystem 总览](filesystem.md) - 返回类总览 diff --git a/docs/api/resources/iloader/canload.md b/docs/api/resources/iloader/canload.md new file mode 100644 index 0000000..a2bf4a3 --- /dev/null +++ b/docs/api/resources/iloader/canload.md @@ -0,0 +1,31 @@ +# IResourceLoader::CanLoad + +```cpp +bool CanLoad(const Containers::String& path) const +``` + +检查此加载器是否能加载指定路径的资源。通过比对路径扩展名与支持列表判断。 + +**参数:** +- `path` - 资源路径 + +**返回:** 如果扩展名在支持列表中则返回 true + +**复杂度:** O(k),k 为扩展名数量 + +**示例:** + +```cpp +bool TextureLoader::CanLoad(const Containers::String& path) const { + Containers::String ext = GetExtension(path); + auto supported = GetSupportedExtensions(); + for (const auto& s : supported) { + if (ext == s) return true; + } + return false; +} +``` + +## 相关文档 + +- [IResourceLoader 总览](iloader.md) - 返回类总览 diff --git a/docs/api/resources/iloader/getdefaultsettings.md b/docs/api/resources/iloader/getdefaultsettings.md new file mode 100644 index 0000000..60daeca --- /dev/null +++ b/docs/api/resources/iloader/getdefaultsettings.md @@ -0,0 +1,25 @@ +# IResourceLoader::GetDefaultSettings + +```cpp +ImportSettings* GetDefaultSettings() const = 0 +``` + +获取此加载器的默认导入设置。纯虚方法,子类返回其特有的默认设置实例。 + +**参数:** 无 + +**返回:** 默认 `ImportSettings` 指针,调用者不持有所有权 + +**复杂度:** O(1) + +**示例:** + +```cpp +ImportSettings* TextureLoader::GetDefaultSettings() const { + return new TextureImportSettings(); +} +``` + +## 相关文档 + +- [IResourceLoader 总览](iloader.md) - 返回类总览 diff --git a/docs/api/resources/iloader/getsupportedextensions.md b/docs/api/resources/iloader/getsupportedextensions.md new file mode 100644 index 0000000..11c796d --- /dev/null +++ b/docs/api/resources/iloader/getsupportedextensions.md @@ -0,0 +1,25 @@ +# IResourceLoader::GetSupportedExtensions + +```cpp +Containers::Array GetSupportedExtensions() const +``` + +获取此加载器支持的文件扩展名列表。用于 `CanLoad` 判断和编辑器中资源类型识别。 + +**参数:** 无 + +**返回:** 支持的扩展名数组(如 `{".png", ".jpg", ".bmp"}`) + +**复杂度:** O(1) + +**示例:** + +```cpp +Containers::Array TextureLoader::GetSupportedExtensions() const { + return {".png", ".jpg", ".jpeg", ".bmp", ".tga", ".dds"}; +} +``` + +## 相关文档 + +- [IResourceLoader 总览](iloader.md) - 返回类总览 diff --git a/docs/api/resources/iloader/iloader.md b/docs/api/resources/iloader/iloader.md new file mode 100644 index 0000000..f893c99 --- /dev/null +++ b/docs/api/resources/iloader/iloader.md @@ -0,0 +1,119 @@ +# IResourceLoader + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` (abstract) + +**描述**: 资源加载器抽象接口,定义了资源加载的标准协议。每个资源类型需要提供对应的加载器实现。 + +## 概述 + +`IResourceLoader` 是资源加载系统的核心抽象接口。它定义了同步和异步加载资源的方法,以及资源类型的查询。`ResourceManager` 通过注册加载器来支持不同类型资源的加载。 + +## LoadResult 结构体 + +加载操作的返回值结构体。 + +```cpp +struct LoadResult { + IResource* resource = nullptr; + bool success = false; + Containers::String errorMessage; + LoadResult() = default; + explicit LoadResult(IResource* res) : resource(res), success(res != nullptr) {} + explicit LoadResult(const Containers::String& error) : success(false), errorMessage(error) {} + explicit LoadResult(bool inSuccess, const Containers::String& error = "") + : success(inSuccess), errorMessage(error) {} + operator bool() const { return success && resource != nullptr; } +}; +``` + +## 公共方法 + +### 资源信息 + +| 方法 | 描述 | +|------|------| +| `ResourceType GetResourceType() const` | 获取此加载器支持的资源类型 | +| `Containers::Array GetSupportedExtensions() const` | 获取支持的文件扩展名列表 | +| `bool CanLoad(const Containers::String& path) const` | 检查此加载器是否能加载指定路径 | +| `ImportSettings* GetDefaultSettings() const` | 获取默认导入设置 | + +### 同步加载 + +| 方法 | 描述 | +|------|------| +| `LoadResult Load(const Containers::String& path, const ImportSettings* settings = nullptr)` | 同步加载资源 | + +### 异步加载 + +| 方法 | 描述 | +|------|------| +| `void LoadAsync(const Containers::String& path, const ImportSettings* settings, std::function callback)` | 异步加载资源(内部默认实现调用同步 Load) | + +### 辅助方法(受保护) + +| 方法 | 描述 | +|------|------| +| `static Containers::Array ReadFileData(const Containers::String& path)` | 读取文件数据 | +| `static Containers::String GetExtension(const Containers::String& path)` | 获取文件扩展名 | + +## 实现说明 + +**注意**: 各资源加载器的 `GetDefaultSettings()` 当前返回 `nullptr`,未返回实际的默认设置对象。 + +## 宏 + +### REGISTER_RESOURCE_LOADER + +自动注册加载器到 ResourceManager 的宏。 + +```cpp +REGISTER_RESOURCE_LOADER(TextureLoader) +``` + +## 使用示例 + +```cpp +class TextureLoader : public IResourceLoader { +public: + ResourceType GetResourceType() const override { + return ResourceType::Texture; + } + + Containers::Array GetSupportedExtensions() const override { + return {".png", ".jpg", ".jpeg", ".bmp", ".tga"}; + } + + bool CanLoad(const Containers::String& path) const override { + Containers::String ext = GetExtension(path); + return ext == ".png" || ext == ".jpg" || ext == ".bmp"; + } + + ImportSettings* GetDefaultSettings() const override { + return new TextureImportSettings(); + } + + LoadResult Load(const Containers::String& path, + const ImportSettings* settings = nullptr) override { + LoadResult result; + auto data = ReadFileData(path); + if (data.Empty()) { + return LoadResult("Failed to read file: " + path); + } + result.resource = new Texture(); + result.success = true; + return result; + } +}; + +// 注册加载器 +ResourceManager::Get().RegisterLoader(new TextureLoader()); +``` + +## 相关文档 + +- [ResourceManager](../resourcemanager/resourcemanager.md) - 资源管理器 +- [AsyncLoader](../asyncloader/asyncloader.md) - 异步加载器 +- [ImportSettings](../importsettings/importsettings.md) - 导入设置 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/iloader/load.md b/docs/api/resources/iloader/load.md new file mode 100644 index 0000000..5151636 --- /dev/null +++ b/docs/api/resources/iloader/load.md @@ -0,0 +1,42 @@ +# IResourceLoader::Load + +```cpp +LoadResult Load(const Containers::String& path, const ImportSettings* settings = nullptr) +``` + +同步加载资源。纯虚方法,由具体加载器实现。从指定路径读取文件数据,解析为对应类型的资源对象。 + +**参数:** +- `path` - 资源文件路径 +- `settings` - 可选的导入设置,用于自定义加载行为 + +**返回:** `LoadResult`,包含加载结果(资源指针、是否成功、错误信息等) + +**复杂度:** O(n),取决于文件大小 + +**示例:** + +```cpp +LoadResult TextureLoader::Load(const Containers::String& path, + const ImportSettings* settings) { + LoadResult result; + auto data = ReadFileData(path); + if (data.Empty()) { + result.errorMessage = "Failed to read file: " + path; + return result; + } + Texture* tex = new Texture(); + if (!tex->LoadFromData(data.Data(), data.Size(), settings)) { + delete tex; + result.errorMessage = "Failed to parse texture data"; + return result; + } + result.resource = tex; + result.success = true; + return result; +} +``` + +## 相关文档 + +- [IResourceLoader 总览](iloader.md) - 返回类总览 diff --git a/docs/api/resources/iloader/loadasync.md b/docs/api/resources/iloader/loadasync.md new file mode 100644 index 0000000..fb39b38 --- /dev/null +++ b/docs/api/resources/iloader/loadasync.md @@ -0,0 +1,34 @@ +# IResourceLoader::LoadAsync + +```cpp +void LoadAsync(const Containers::String& path, const ImportSettings* settings, + std::function callback) +``` + +异步加载资源。默认实现直接调用同步 `Load` 方法并在当前线程执行回调。子类可重写以实现真正的多线程异步加载。 + +**参数:** +- `path` - 资源路径 +- `settings` - 导入设置(可为 nullptr) +- `callback` - 加载完成回调函数 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +void AsyncTextureLoader::LoadAsync(const Containers::String& path, + const ImportSettings* settings, + std::function callback) { + std::thread([this, path, settings, callback]() { + LoadResult result = Load(path, settings); + callback(result); // 回调可在工作线程执行 + }).detach(); +} +``` + +## 相关文档 + +- [IResourceLoader 总览](iloader.md) - 返回类总览 diff --git a/docs/api/resources/importsettings/importsettings.md b/docs/api/resources/importsettings/importsettings.md new file mode 100644 index 0000000..2c942e4 --- /dev/null +++ b/docs/api/resources/importsettings/importsettings.md @@ -0,0 +1,173 @@ +# ImportSettings + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` (abstract) + +**描述**: 资源导入设置抽象基类,定义资源导入时的配置选项接口。 + +## 概述 + +`ImportSettings` 是所有资源导入设置的抽象基类。它提供了克隆和 JSON 序列化接口,允许不同资源类型定义各自的导入选项。引擎内置了两个具体实现:`TextureImportSettings` 和 `MeshImportSettings`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `virtual Core::UniqueRef Clone() const = 0` | 克隆一份设置 | +| `virtual bool LoadFromJSON(const Containers::String& json)` | 从 JSON 加载设置(当前返回 false - stub) | +| `virtual Containers::String SaveToJSON() const` | 保存为 JSON 字符串(当前返回空字符串 - stub) | + +--- + +## TextureImportSettings + +纹理导入设置,继承自 `ImportSettings`。 + +**头文件**: `XCEngine/Resources/TextureImportSettings.h` + +## 实现说明 + +**注意**: `LoadFromJSON()` 和 `SaveToJSON()` 当前为 stub 实现。 + +### 枚举类型 + +#### MipmapFilter + +| 值 | 描述 | +|----|------| +| `Box` | Box 滤波器 | +| `Kaiser` | Kaiser 滤波器 | + +#### CompressionQuality + +| 值 | 描述 | +|----|------| +| `Low` | 低质量 | +| `Medium` | 中等质量 | +| `High` | 高质量 | +| `Ultra` | 超高质量 | + +### 公共方法 + +| 方法 | 描述 | +|------|------| +| `void SetTextureType(TextureType type)` | 设置纹理类型 | +| `TextureType GetTextureType() const` | 获取纹理类型 | +| `void SetTargetFormat(TextureFormat format)` | 设置目标格式 | +| `TextureFormat GetTargetFormat() const` | 获取目标格式 | +| `void SetGenerateMipmaps(bool generate)` | 设置是否生成 Mipmap | +| `bool GetGenerateMipmaps() const` | 获取是否生成 Mipmap | +| `void SetMipmapFilter(MipmapFilter filter)` | 设置 Mipmap 滤波器 | +| `MipmapFilter GetMipmapFilter() const` | 获取 Mipmap 滤波器 | +| `void SetMaxAnisotropy(Core::uint32 anisotropy)` | 设置最大各向异性级别 | +| `Core::uint32 GetMaxAnisotropy() const` | 获取最大各向异性级别 | +| `void SetSRGB(bool srgb)` | 设置是否 sRGB | +| `bool GetSRGB() const` | 获取 sRGB 设置 | +| `void SetFlipVertical(bool flip)` | 设置是否垂直翻转 | +| `bool GetFlipVertical() const` | 获取垂直翻转设置 | +| `void SetFlipHorizontal(bool flip)` | 设置是否水平翻转 | +| `bool GetFlipHorizontal() const` | 获取水平翻转设置 | +| `void SetBorderColor(const Math::Vector3& color)` | 设置边框颜色 | +| `const Math::Vector3& GetBorderColor() const` | 获取边框颜色 | +| `void SetCompressionQuality(CompressionQuality quality)` | 设置压缩质量 | +| `CompressionQuality GetCompressionQuality() const` | 获取压缩质量 | +| `void SetUseHardwareCompression(bool use)` | 设置是否使用硬件压缩 | +| `bool GetUseHardwareCompression() const` | 获取硬件压缩设置 | +| `void SetMaxSize(Core::uint32 size)` | 设置最大纹理尺寸 | +| `Core::uint32 GetMaxSize() const` | 获取最大纹理尺寸 | +| `void SetGenerateNormalMap(bool generate)` | 设置是否生成法线贴图 | +| `bool GetGenerateNormalMap() const` | 获取法线贴图生成设置 | +| `void SetNormalMapStrength(float strength)` | 设置法线贴图强度 | +| `float GetNormalMapStrength() const` | 获取法线贴图强度 | + +--- + +## MeshImportSettings + +网格导入设置,继承自 `ImportSettings`。 + +**头文件**: `XCEngine/Resources/MeshImportSettings.h` + +## 实现说明 + +**注意**: `LoadFromJSON()` 和 `SaveToJSON()` 当前为 stub 实现。 + +### MeshImportFlags + +| 值 | 描述 | +|----|------| +| `None` | 无特殊标志 | +| `FlipUVs` | 翻转 UV 坐标 | +| `FlipWindingOrder` | 翻转绕序 | +| `GenerateNormals` | 生成法线 | +| `GenerateTangents` | 生成切线 | +| `OptimizeMesh` | 优化网格 | +| `ImportSkinning` | 导入骨骼蒙皮 | +| `ImportAnimations` | 导入动画 | +| `ImportMaterials` | 导入材质 | +| `ImportCameras` | 导入相机 | +| `ImportLights` | 导入灯光 | + +支持位运算组合(`operator|`、`operator&`、`operator~`)。 + +### 公共方法 + +| 方法 | 描述 | +|------|------| +| `void SetImportFlags(MeshImportFlags flags)` | 设置导入标志 | +| `MeshImportFlags GetImportFlags() const` | 获取导入标志 | +| `void AddImportFlag(MeshImportFlags flag)` | 添加单个导入标志 | +| `void RemoveImportFlag(MeshImportFlags flag)` | 移除单个导入标志 | +| `bool HasImportFlag(MeshImportFlags flag) const` | 检查是否包含某标志 | +| `void SetScale(float scale)` | 设置缩放 | +| `float GetScale() const` | 获取缩放 | +| `void SetOffset(const Math::Vector3& offset)` | 设置偏移 | +| `const Math::Vector3& GetOffset() const` | 获取偏移 | +| `void SetAxisConversion(bool convert)` | 设置轴转换 | +| `bool GetAxisConversion() const` | 获取轴转换设置 | +| `void SetMergeMeshes(bool merge)` | 设置是否合并网格 | +| `bool GetMergeMeshes() const` | 获取合并网格设置 | +| `void SetOptimizeThreshold(float threshold)` | 设置优化阈值 | +| `float GetOptimizeThreshold() const` | 获取优化阈值 | +| `void SetImportScale(float scale)` | 设置导入缩放 | +| `float GetImportScale() const` | 获取导入缩放 | +| `void SetThreshold(float threshold)` | 设置阈值 | +| `float GetThreshold() const` | 获取阈值 | + +## 使用示例 + +```cpp +#include +#include + +// 纹理导入设置 +TextureImportSettings texSettings; +texSettings.SetTextureType(TextureType::Texture2D); +texSettings.SetGenerateMipmaps(true); +texSettings.SetSRGB(true); +texSettings.SetCompressionQuality(CompressionQuality::High); +texSettings.SetMaxAnisotropy(16); + +// 加载设置 +texSettings.LoadFromJSON(R"({"sRGB":true,"maxAnisotropy":8})"); + +// 保存设置 +Containers::String json = texSettings.SaveToJSON(); + +// 网格导入设置 +MeshImportSettings meshSettings; +meshSettings.SetImportFlags(MeshImportFlags::FlipUVs | MeshImportFlags::GenerateNormals); +meshSettings.SetScale(1.0f); +meshSettings.SetAxisConversion(true); + +// 使用设置加载资源 +ResourceHandle tex = ResourceManager::Get().Load("tex.png", &texSettings); +ResourceHandle mesh = ResourceManager::Get().Load("model.fbx", &meshSettings); +``` + +## 相关文档 + +- [IResourceLoader](../iloader/iloader.md) - 资源加载器 +- [ResourceManager](../resourcemanager/resourcemanager.md) - 资源管理器 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/iresource/initialize.md b/docs/api/resources/iresource/initialize.md new file mode 100644 index 0000000..641b958 --- /dev/null +++ b/docs/api/resources/iresource/initialize.md @@ -0,0 +1,34 @@ +# IResource::Initialize + +```cpp +void Initialize(const ConstructParams& params) +``` + +使用构造参数初始化资源。将参数中的名称、路径、GUID 和内存大小写入对应成员变量,并将资源标记为有效状态。 + +**参数:** +- `params` - 包含资源名称、路径、GUID 和内存大小的构造参数结构体 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +class MyResource : public IResource { +public: + MyResource() { + ConstructParams params; + params.name = "player_texture"; + params.path = "textures/player.png"; + params.guid = ResourceGUID::Generate(params.path); + params.memorySize = 1024 * 1024; // 1MB + Initialize(params); + } +}; +``` + +## 相关文档 + +- [IResource 总览](iresource.md) - 返回类总览 diff --git a/docs/api/resources/iresource/iresource.md b/docs/api/resources/iresource/iresource.md new file mode 100644 index 0000000..2ce20d7 --- /dev/null +++ b/docs/api/resources/iresource/iresource.md @@ -0,0 +1,57 @@ +# IResource + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` (abstract) + +**描述**: 资源基类接口,所有具体资源类型(Texture、Mesh、Material 等)都必须继承自此类。 + +## 概述 + +`IResource` 是 XCEngine 资源管理系统的核心抽象基类。它定义了所有资源共有的基本属性和行为,包括资源类型、名称、路径、GUID、内存大小和有效性状态。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `ResourceType GetType() const` | 获取资源类型 | +| `const Containers::String& GetName() const` | 获取资源名称 | +| `const Containers::String& GetPath() const` | 获取资源路径 | +| `ResourceGUID GetGUID() const` | 获取全局唯一标识符 | +| `bool IsValid() const` | 检查资源是否有效 | +| `size_t GetMemorySize() const` | 获取资源占用的内存大小(字节) | +| `void Release()` | 释放资源引用 | +| `void Initialize(const ConstructParams& params)` | 使用构造参数初始化资源 | +| `void SetInvalid()` | 将资源标记为无效 | + +### 构造参数 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `m_name` | `Containers::String` | 资源名称 | +| `m_path` | `Containers::String` | 资源路径 | +| `m_guid` | `ResourceGUID` | 全局唯一标识符 | +| `m_isValid` | `bool` | 资源是否有效 | +| `m_memorySize` | `size_t` | 内存占用大小 | + +## 使用示例 + +```cpp +class MyResource : public IResource { +public: + ResourceType GetType() const override { return ResourceType::Custom; } + const Containers::String& GetName() const override { return m_name; } + const Containers::String& GetPath() const override { return m_path; } + ResourceGUID GetGUID() const override { return m_guid; } + bool IsValid() const override { return m_isValid; } + size_t GetMemorySize() const override { return m_memorySize; } + void Release() override { /* 释放逻辑 */ } +}; +``` + +## 相关文档 + +- [ResourceHandle](../resourcehandle/resourcehandle.md) - 资源句柄 +- [ResourceManager](../resourcemanager/resourcemanager.md) - 资源管理器 +- [ResourceTypes](../resourcetypes/resourcetypes.md) - 资源类型定义 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/iresource/release.md b/docs/api/resources/iresource/release.md new file mode 100644 index 0000000..2969aa2 --- /dev/null +++ b/docs/api/resources/iresource/release.md @@ -0,0 +1,33 @@ +# IResource::Release + +```cpp +virtual void Release() = 0 +``` + +释放资源引用。纯虚方法,由具体资源类实现,用于执行资源特有的清理逻辑(如释放 GPU 资源、释放内存等)。在 `ResourceHandle` 析构或调用 `Reset()` 时会自动触发。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) 或 O(n),取决于具体实现 + +**示例:** + +```cpp +class Texture : public IResource { +public: + void Release() override { + if (m_rhiTexture) { + m_rhiTexture->Release(); + m_rhiTexture = nullptr; + } + m_pixelData.Clear(); + m_isValid = false; + } +}; +``` + +## 相关文档 + +- [IResource 总览](iresource.md) - 返回类总览 diff --git a/docs/api/resources/iresource/setinvalid.md b/docs/api/resources/iresource/setinvalid.md new file mode 100644 index 0000000..4b0530e --- /dev/null +++ b/docs/api/resources/iresource/setinvalid.md @@ -0,0 +1,28 @@ +# IResource::SetInvalid + +```cpp +void SetInvalid() +``` + +将资源标记为无效状态。此方法用于在加载失败或资源损坏时将 `m_isValid` 设为 false,之后调用 `IsValid()` 将返回 false。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +void LoadFailed() { + texture->SetInvalid(); + if (!texture->IsValid()) { + // 处理资源无效情况 + } +} +``` + +## 相关文档 + +- [IResource 总览](iresource.md) - 返回类总览 diff --git a/docs/api/resources/material/material.md b/docs/api/resources/material/material.md new file mode 100644 index 0000000..343992b --- /dev/null +++ b/docs/api/resources/material/material.md @@ -0,0 +1,151 @@ +# Material + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` + +**描述**: 材质资源类,管理渲染所需的着色器和属性参数。 + +## 概述 + +`Material` 是 XCEngine 中的材质资源类,继承自 `IResource`。它管理材质关联的着色器和各种属性参数(浮点数、向量、纹理等),并支持将属性数据打包到常量缓冲区。 + +## 头文件 + +```cpp +#include +``` + +## 枚举类型 + +### MaterialPropertyType + +材质属性类型枚举。 + +| 值 | 描述 | +|----|------| +| `Float` | 单精度浮点数 | +| `Float2` | 二维浮点向量 | +| `Float3` | 三维浮点向量 | +| `Float4` | 四维浮点向量 | +| `Int` | 整数 | +| `Int2` | 二维整数向量 | +| `Int3` | 三维整数向量 | +| `Int4` | 四维整数向量 | +| `Bool` | 布尔值 | +| `Texture` | 纹理资源 | +| `Cubemap` | 立方体贴图资源 | + +## 结构体 + +### MaterialProperty + +材质属性结构体。 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `name` | `Containers::String` | 属性名称 | +| `type` | `MaterialPropertyType` | 属性类型 | +| `value` | `union` | 属性值(float/int/bool) | +| `refCount` | `Core::uint32` | 引用计数 | + +## 公共方法 + +### 基础属性 + +| 方法 | 描述 | +|------|------| +| `ResourceType GetType() const` | 返回 `ResourceType::Material` | +| `const Containers::String& GetName() const` | 获取材质名称 | +| `const Containers::String& GetPath() const` | 获取材质路径 | +| `ResourceGUID GetGUID() const` | 获取全局唯一标识符 | +| `bool IsValid() const` | 检查材质是否有效 | +| `size_t GetMemorySize() const` | 获取内存大小 | +| `void Release()` | 释放材质引用 | + +### 着色器管理 + +| 方法 | 描述 | +|------|------| +| `void SetShader(const ResourceHandle& shader)` | 设置材质着色器 | +| `Shader* GetShader() const` | 获取材质着色器 | + +### 属性设置 + +| 方法 | 描述 | +|------|------| +| `void SetFloat(const Containers::String& name, float value)` | 设置浮点属性 | +| `void SetFloat2(const Containers::String& name, const Math::Vector2& value)` | 设置 Vector2 属性 | +| `void SetFloat3(const Containers::String& name, const Math::Vector3& value)` | 设置 Vector3 属性 | +| `void SetFloat4(const Containers::String& name, const Math::Vector4& value)` | 设置 Vector4 属性 | +| `void SetInt(const Containers::String& name, Core::int32 value)` | 设置整数属性 | +| `void SetBool(const Containers::String& name, bool value)` | 设置布尔属性 | +| `void SetTexture(const Containers::String& name, const ResourceHandle& texture)` | 设置纹理属性 | + +### 属性获取 + +| 方法 | 描述 | +|------|------| +| `float GetFloat(const Containers::String& name) const` | 获取浮点属性 | +| `Math::Vector2 GetFloat2(const Containers::String& name) const` | 获取 Vector2 属性 | +| `Math::Vector3 GetFloat3(const Containers::String& name) const` | 获取 Vector3 属性 | +| `Math::Vector4 GetFloat4(const Containers::String& name) const` | 获取 Vector4 属性 | +| `Core::int32 GetInt(const Containers::String& name) const` | 获取整数属性 | +| `bool GetBool(const Containers::String& name) const` | 获取布尔属性 | +| `ResourceHandle GetTexture(const Containers::String& name) const` | 获取纹理属性 | + +### 常量缓冲区 + +| 方法 | 描述 | +|------|------| +| `const Containers::Array& GetConstantBufferData() const` | 获取常量缓冲区数据 | +| `void UpdateConstantBuffer()` | 更新常量缓冲区数据 | + +### 属性管理 + +| 方法 | 描述 | +|------|------| +| `bool HasProperty(const Containers::String& name) const` | 检查属性是否存在 | +| `void RemoveProperty(const Containers::String& name)` | 移除属性 | +| `void ClearAllProperties()` | 清空所有属性 | + +## 实现说明 + +**注意**: `MaterialLoader::ParseMaterialData()` 为 stub,始终返回 true。`MaterialLoader::Load()` 仅为示例实现,未解析材质属性。 + +## 使用示例 + +```cpp +// 加载材质 +ResourceHandle mat = ResourceManager::Get().Load("materials/player.mat"); + +// 设置着色器 +mat->SetShader(shaderHandle); + +// 设置各种属性 +mat->SetFloat("roughness", 0.5f); +mat->SetFloat3("albedo", Math::Vector3(1.0f, 0.8f, 0.6f)); +mat->SetTexture("albedoMap", albedoTex); +mat->SetTexture("normalMap", normalTex); +mat->SetInt("normalScale", 1); + +// 获取属性 +float roughness = mat->GetFloat("roughness"); +Math::Vector3 albedo = mat->GetFloat3("albedo"); + +// 检查属性 +if (mat->HasProperty("metallic")) { + float metallic = mat->GetFloat("metallic"); +} + +// 更新常量缓冲区 +mat->UpdateConstantBuffer(); +auto cbData = mat->GetConstantBufferData(); +``` + +## 相关文档 + +- [IResource](../iresource/iresource.md) - 资源基类 +- [Shader](../shader/shader.md) - 着色器资源 +- [Texture](../texture/texture.md) - 纹理资源 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/material/setfloat.md b/docs/api/resources/material/setfloat.md new file mode 100644 index 0000000..a7bf890 --- /dev/null +++ b/docs/api/resources/material/setfloat.md @@ -0,0 +1,27 @@ +# Material::SetFloat + +```cpp +void SetFloat(const Containers::String& name, float value) +``` + +设置材质浮点属性。 + +**参数:** +- `name` - 属性名称 +- `value` - 属性值 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +mat->SetFloat("roughness", 0.5f); +mat->SetFloat("metallic", 0.0f); +mat->SetFloat("emissionStrength", 2.0f); +``` + +## 相关文档 + +- [Material 总览](material.md) - 返回类总览 diff --git a/docs/api/resources/material/setshader.md b/docs/api/resources/material/setshader.md new file mode 100644 index 0000000..d3adf4d --- /dev/null +++ b/docs/api/resources/material/setshader.md @@ -0,0 +1,26 @@ +# Material::SetShader + +```cpp +void SetShader(const ResourceHandle& shader) +``` + +设置材质使用的着色器。 + +**参数:** +- `shader` - 着色器资源句柄 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +ResourceHandle vs = ResourceManager::Get().Load("shaders/vertex.glsl"); +ResourceHandle fs = ResourceManager::Get().Load("shaders/fragment.glsl"); +mat->SetShader(vs); +``` + +## 相关文档 + +- [Material 总览](material.md) - 返回类总览 diff --git a/docs/api/resources/material/settexture.md b/docs/api/resources/material/settexture.md new file mode 100644 index 0000000..02f169f --- /dev/null +++ b/docs/api/resources/material/settexture.md @@ -0,0 +1,28 @@ +# Material::SetTexture + +```cpp +void SetTexture(const Containers::String& name, const ResourceHandle& texture) +``` + +设置材质纹理属性。 + +**参数:** +- `name` - 属性名称 +- `texture` - 纹理资源句柄 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +ResourceHandle albedoTex = ResourceManager::Get().Load("textures/albedo.png"); +ResourceHandle normalTex = ResourceManager::Get().Load("textures/normal.png"); +mat->SetTexture("albedoMap", albedoTex); +mat->SetTexture("normalMap", normalTex); +``` + +## 相关文档 + +- [Material 总览](material.md) - 返回类总览 diff --git a/docs/api/resources/material/updateconstantbuffer.md b/docs/api/resources/material/updateconstantbuffer.md new file mode 100644 index 0000000..5854f16 --- /dev/null +++ b/docs/api/resources/material/updateconstantbuffer.md @@ -0,0 +1,26 @@ +# Material::UpdateConstantBuffer + +```cpp +void UpdateConstantBuffer() +``` + +更新材质常量缓冲区。将所有属性值打包到常量缓冲区的二进制数据中,供 GPU 着色器使用。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n),n 为属性数量 + +**示例:** + +```cpp +mat->SetFloat("roughness", 0.5f); +mat->SetFloat3("albedo", Math::Vector3(1.0f, 0.8f, 0.6f)); +mat->UpdateConstantBuffer(); +auto cbData = mat->GetConstantBufferData(); +``` + +## 相关文档 + +- [Material 总览](material.md) - 返回类总览 diff --git a/docs/api/resources/mesh/addsection.md b/docs/api/resources/mesh/addsection.md new file mode 100644 index 0000000..f7dc044 --- /dev/null +++ b/docs/api/resources/mesh/addsection.md @@ -0,0 +1,30 @@ +# Mesh::AddSection + +```cpp +void AddSection(const MeshSection& section) +``` + +添加网格分段(Submesh)。一个 Mesh 可以包含多个分段,每个分段对应一组索引和不同的材质。 + +**参数:** +- `section` - 网格分段描述结构体 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +MeshSection section; +section.baseVertex = 0; +section.vertexCount = 1000; +section.startIndex = 0; +section.indexCount = 3000; +section.materialID = 0; +mesh->AddSection(section); +``` + +## 相关文档 + +- [Mesh 总览](mesh.md) - 返回类总览 diff --git a/docs/api/resources/mesh/mesh.md b/docs/api/resources/mesh/mesh.md new file mode 100644 index 0000000..388275c --- /dev/null +++ b/docs/api/resources/mesh/mesh.md @@ -0,0 +1,150 @@ +# Mesh + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` + +**描述**: 网格资源类,管理 3D 模型的顶点数据、索引数据和网格分段信息。 + +## 概述 + +`Mesh` 是 XCEngine 中的网格资源类,继承自 `IResource`。它管理网格的顶点数据(位置、法线、UV、切线、颜色、骨骼权重等)、索引数据和网格分段(submesh)。 + +## 头文件 + +```cpp +#include +``` + +## 枚举类型 + +### VertexAttribute + +顶点属性标志枚举(可组合)。 + +| 值 | 描述 | +|----|------| +| `Position` | 位置坐标 | +| `Normal` | 法线 | +| `Tangent` | 切线 | +| `Color` | 顶点颜色 | +| `UV0` | 第一组纹理坐标 | +| `UV1` | 第二组纹理坐标 | +| `UV2` | 第三组纹理坐标 | +| `UV3` | 第四组纹理坐标 | +| `BoneWeights` | 骨骼权重 | +| `BoneIndices` | 骨骼索引 | + +## MeshSection 结构体 + +网格分段(Submesh)描述。 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `baseVertex` | `Core::uint32` | 基础顶点索引 | +| `vertexCount` | `Core::uint32` | 顶点数量 | +| `startIndex` | `Core::uint32` | 起始索引 | +| `indexCount` | `Core::uint32` | 索引数量 | +| `materialID` | `Core::uint32` | 对应材质 ID | + +## 公共方法 + +### 基础属性 + +| 方法 | 描述 | +|------|------| +| `ResourceType GetType() const` | 返回 `ResourceType::Mesh` | +| `const Containers::String& GetName() const` | 获取网格名称 | +| `const Containers::String& GetPath() const` | 获取网格路径 | +| `ResourceGUID GetGUID() const` | 获取全局唯一标识符 | +| `bool IsValid() const` | 检查网格是否有效 | +| `size_t GetMemorySize() const` | 获取内存大小 | +| `void Release()` | 释放网格引用 | + +### 顶点数据 + +| 方法 | 描述 | +|------|------| +| `void SetVertexData(const void* data, size_t size, Core::uint32 vertexCount, Core::uint32 vertexStride, VertexAttribute attributes)` | 设置顶点数据 | +| `const void* GetVertexData() const` | 获取顶点数据指针 | +| `size_t GetVertexDataSize() const` | 获取顶点数据大小 | +| `Core::uint32 GetVertexCount() const` | 获取顶点数量 | +| `Core::uint32 GetVertexStride() const` | 获取顶点结构体大小(字节) | +| `VertexAttribute GetVertexAttributes() const` | 获取顶点属性标志 | + +### 索引数据 + +| 方法 | 描述 | +|------|------| +| `void SetIndexData(const void* data, size_t size, Core::uint32 indexCount, bool use32Bit)` | 设置索引数据 | +| `const void* GetIndexData() const` | 获取索引数据指针 | +| `size_t GetIndexDataSize() const` | 获取索引数据大小 | +| `Core::uint32 GetIndexCount() const` | 获取索引数量 | +| `bool IsUse32BitIndex() const` | 是否使用 32 位索引 | + +### 网格分段 + +| 方法 | 描述 | +|------|------| +| `void AddSection(const MeshSection& section)` | 添加网格分段 | +| `const Containers::Array& GetSections() const` | 获取所有分段 | + +## 使用示例 + +```cpp +// 加载网格 +ResourceHandle mesh = ResourceManager::Get().Load("models/player.fbx"); + +// 手动设置顶点数据 +struct Vertex { + float position[3]; + float normal[3]; + float uv[2]; +}; + +Containers::Array vertices; +vertices.Resize(vertexCount); +// ... 填充顶点数据 ... + +mesh->SetVertexData( + vertices.Data(), + vertices.Size() * sizeof(Vertex), + vertexCount, + sizeof(Vertex), + VertexAttribute::Position | VertexAttribute::Normal | VertexAttribute::UV0 +); + +// 设置索引数据 +Containers::Array indices; +indices.Resize(indexCount); +// ... 填充索引数据 ... + +mesh->SetIndexData( + indices.Data(), + indices.Size() * sizeof(uint32_t), + indexCount, + true // 32 位索引 +); + +// 添加分段(一个网格可能有多个材质) +MeshSection section; +section.baseVertex = 0; +section.vertexCount = vertexCount; +section.startIndex = 0; +section.indexCount = indexCount; +section.materialID = 0; +mesh->AddSection(section); + +// 访问数据 +uint32_t vCount = mesh->GetVertexCount(); +uint32_t iCount = mesh->GetIndexCount(); +auto sections = mesh->GetSections(); +``` + +## 相关文档 + +- [IResource](../iresource/iresource.md) - 资源基类 +- [Material](../material/material.md) - 材质资源 +- [ResourceManager](../resourcemanager/resourcemanager.md) - 资源管理器 +- [Resources 总览](../resources.md) - 返回模块总览 +- **实现说明**: `MeshLoader::Load()` 仅为示例实现,不解析 FBX/OBJ 等格式的实际网格数据 diff --git a/docs/api/resources/mesh/setindexdata.md b/docs/api/resources/mesh/setindexdata.md new file mode 100644 index 0000000..06fd615 --- /dev/null +++ b/docs/api/resources/mesh/setindexdata.md @@ -0,0 +1,30 @@ +# Mesh::SetIndexData + +```cpp +void SetIndexData(const void* data, size_t size, Core::uint32 indexCount, bool use32Bit) +``` + +设置网格索引数据。复制索引缓冲数据到内部存储。 + +**参数:** +- `data` - 索引数据指针 +- `size` - 数据大小(字节) +- `indexCount` - 索引数量 +- `use32Bit` - 是否使用 32 位索引(否则使用 16 位) + +**返回:** 无 + +**复杂度:** O(n),n 为索引数据大小 + +**示例:** + +```cpp +Containers::Array indices; +// ... 填充索引数据 ... +mesh->SetIndexData(indices.Data(), indices.Size() * sizeof(uint32_t), + indices.Size(), true); +``` + +## 相关文档 + +- [Mesh 总览](mesh.md) - 返回类总览 diff --git a/docs/api/resources/mesh/setvertexdata.md b/docs/api/resources/mesh/setvertexdata.md new file mode 100644 index 0000000..38c5754 --- /dev/null +++ b/docs/api/resources/mesh/setvertexdata.md @@ -0,0 +1,37 @@ +# Mesh::SetVertexData + +```cpp +void SetVertexData(const void* data, size_t size, Core::uint32 vertexCount, + Core::uint32 vertexStride, VertexAttribute attributes) +``` + +设置网格顶点数据。复制顶点缓冲数据到内部存储。 + +**参数:** +- `data` - 顶点数据指针 +- `size` - 数据大小(字节) +- `vertexCount` - 顶点数量 +- `vertexStride` - 单个顶点结构体大小(字节) +- `attributes` - 顶点属性标志组合 + +**返回:** 无 + +**复杂度:** O(n),n 为顶点数据大小 + +**示例:** + +```cpp +struct Vertex { + float position[3]; + float normal[3]; + float uv[2]; +}; + +mesh->SetVertexData(vertices.Data(), vertices.Size() * sizeof(Vertex), + vertexCount, sizeof(Vertex), + VertexAttribute::Position | VertexAttribute::Normal | VertexAttribute::UV0); +``` + +## 相关文档 + +- [Mesh 总览](mesh.md) - 返回类总览 diff --git a/docs/api/resources/resourcecache/add.md b/docs/api/resources/resourcecache/add.md new file mode 100644 index 0000000..2d7ee72 --- /dev/null +++ b/docs/api/resources/resourcecache/add.md @@ -0,0 +1,25 @@ +# ResourceCache::Add + +```cpp +void Add(ResourceGUID guid, IResource* resource) +``` + +添加资源到缓存。将资源和 GUID 关联并记录内存大小、访问时间。线程安全。 + +**参数:** +- `guid` - 资源全局唯一标识符 +- `resource` - 资源指针 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +cache.Add(guid, resource); +``` + +## 相关文档 + +- [ResourceCache 总览](resourcecache.md) - 返回类总览 diff --git a/docs/api/resources/resourcecache/flush.md b/docs/api/resources/resourcecache/flush.md new file mode 100644 index 0000000..5b83ee7 --- /dev/null +++ b/docs/api/resources/resourcecache/flush.md @@ -0,0 +1,23 @@ +# ResourceCache::Flush + +```cpp +void Flush() +``` + +清空缓存,释放所有资源。将所有缓存条目标记为待释放状态,调用每个资源的 `Release()` 方法。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +cache.Flush(); +``` + +## 相关文档 + +- [ResourceCache 总览](resourcecache.md) - 返回类总览 diff --git a/docs/api/resources/resourcecache/getlrulist.md b/docs/api/resources/resourcecache/getlrulist.md new file mode 100644 index 0000000..6e850f9 --- /dev/null +++ b/docs/api/resources/resourcecache/getlrulist.md @@ -0,0 +1,27 @@ +# ResourceCache::GetLRUList + +```cpp +Containers::Array GetLRUList(size_t count) const +``` + +获取最近最少使用的 GUID 列表。按 LRU 顺序返回前 `count` 个资源 GUID。 + +**参数:** +- `count` - 要获取的 GUID 数量 + +**返回:** 最近最少使用的 GUID 数组 + +**复杂度:** O(n) + +**示例:** + +```cpp +auto lruList = cache.GetLRUList(10); +for (const auto& guid : lruList) { + // 标记或处理这些资源... +} +``` + +## 相关文档 + +- [ResourceCache 总览](resourcecache.md) - 返回类总览 diff --git a/docs/api/resources/resourcecache/onmemorypressure.md b/docs/api/resources/resourcecache/onmemorypressure.md new file mode 100644 index 0000000..5b6efa2 --- /dev/null +++ b/docs/api/resources/resourcecache/onmemorypressure.md @@ -0,0 +1,25 @@ +# ResourceCache::OnMemoryPressure + +```cpp +void OnMemoryPressure(size_t requiredBytes) +``` + +内存压力回调。当系统内存紧张时调用此方法,从 LRU 列表头部开始驱逐资源,直到释放足够空间。 + +**参数:** +- `requiredBytes` - 需要释放的字节数 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +// 需要 100MB 空间 +cache.OnMemoryPressure(100 * 1024 * 1024); +``` + +## 相关文档 + +- [ResourceCache 总览](resourcecache.md) - 返回类总览 diff --git a/docs/api/resources/resourcecache/resourcecache.md b/docs/api/resources/resourcecache/resourcecache.md new file mode 100644 index 0000000..aea2d6e --- /dev/null +++ b/docs/api/resources/resourcecache/resourcecache.md @@ -0,0 +1,79 @@ +# ResourceCache + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` + +**描述**: 资源缓存管理类,使用 LRU(最近最少使用)策略管理内存压力下的资源驱逐。 + +## 概述 + +`ResourceCache` 实现了资源的内存缓存管理。它跟踪每个资源的访问时间和访问次数,在内存压力下自动驱逐最近最少使用的资源,确保内存使用不超过预算。 + +## CacheEntry 结构体 + +缓存条目结构体。 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `resource` | `IResource*` | 资源指针 | +| `guid` | `ResourceGUID` | 全局唯一标识符 | +| `memorySize` | `size_t` | 内存大小 | +| `lastAccessTime` | `Core::uint64` | 上次访问时间戳 | +| `accessCount` | `Core::uint32` | 访问次数 | + +### 构造与静态方法 + +| 方法 | 描述 | +|------|------| +| `CacheEntry()` | 默认构造 | +| `CacheEntry(IResource* res, size_t size)` | 从资源和大小构造 | +| `static Core::uint64 GetCurrentTick()` | 获取当前时间戳 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `ResourceCache()` | 默认构造函数 | +| `~ResourceCache()` | 析构函数 | +| `void Add(ResourceGUID guid, IResource* resource)` | 添加资源到缓存 | +| `void Remove(ResourceGUID guid)` | 从缓存中移除资源 | +| `IResource* Find(ResourceGUID guid) const` | 查找资源 | +| `void Touch(ResourceGUID guid)` | 更新资源的访问时间(LRU) | +| `size_t GetSize() const` | 获取缓存中资源数量 | +| `size_t GetMemoryUsage() const` | 获取缓存内存使用量(字节) | +| `void SetMemoryBudget(size_t bytes)` | 设置内存预算 | +| `size_t GetMemoryBudget() const` | 获取内存预算 | +| `void OnMemoryPressure(size_t requiredBytes)` | 内存压力回调,驱逐资源以释放空间 | +| `void OnZeroRefCount(ResourceGUID guid)` | 当引用计数为零时的回调(当前为空实现) | +| `void Flush()` | 清空缓存,释放所有资源(当前为部分实现) | +| `void Clear()` | 清空缓存但不释放资源 | +| `Containers::Array GetLRUList(size_t count) const` | 获取最近最少使用的 GUID 列表 | + +## 使用示例 + +```cpp +ResourceCache cache; +cache.SetMemoryBudget(512 * 1024 * 1024); // 512MB 预算 + +// 添加资源 +cache.Add(guid, resource); + +// 访问资源(更新 LRU) +cache.Touch(guid); + +// 查找资源 +IResource* res = cache.Find(guid); + +// 内存压力时自动驱逐 +cache.OnMemoryPressure(100 * 1024 * 1024); // 需要 100MB + +// 获取最少使用的资源 +auto lruList = cache.GetLRUList(10); +``` + +## 相关文档 + +- [ResourceManager](../resourcemanager/resourcemanager.md) - 资源管理器 +- [IResource](../iresource/iresource.md) - 资源基类 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/resourcecache/touch.md b/docs/api/resources/resourcecache/touch.md new file mode 100644 index 0000000..138d7b7 --- /dev/null +++ b/docs/api/resources/resourcecache/touch.md @@ -0,0 +1,27 @@ +# ResourceCache::Touch + +```cpp +void Touch(ResourceGUID guid) +``` + +更新资源的最近访问时间。当缓存条目被命中时调用,用于 LRU 驱逐算法判断资源的访问热度。 + +**参数:** +- `guid` - 资源全局唯一标识符 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +IResource* res = cache.Find(guid); +if (res) { + cache.Touch(guid); // 更新 LRU +} +``` + +## 相关文档 + +- [ResourceCache 总览](resourcecache.md) - 返回类总览 diff --git a/docs/api/resources/resourcehandle/get.md b/docs/api/resources/resourcehandle/get.md new file mode 100644 index 0000000..bf010d3 --- /dev/null +++ b/docs/api/resources/resourcehandle/get.md @@ -0,0 +1,27 @@ +# ResourceHandle::Get + +```cpp +T* Get() const +``` + +获取资源裸指针。返回句柄内部持有的资源指针,不进行任何引用计数操作。 + +**参数:** 无 + +**返回:** 资源裸指针,可能为 `nullptr`(当句柄为空时) + +**复杂度:** O(1) + +**示例:** + +```cpp +ResourceHandle tex = ResourceManager::Get().Load("tex.png"); +Texture* raw = tex.Get(); +if (raw != nullptr) { + uint32_t w = raw->GetWidth(); +} +``` + +## 相关文档 + +- [ResourceHandle 总览](resourcehandle.md) - 返回类总览 diff --git a/docs/api/resources/resourcehandle/getguid.md b/docs/api/resources/resourcehandle/getguid.md new file mode 100644 index 0000000..8dd379b --- /dev/null +++ b/docs/api/resources/resourcehandle/getguid.md @@ -0,0 +1,27 @@ +# ResourceHandle::GetGUID + +```cpp +ResourceGUID GetGUID() const +``` + +获取资源的全局唯一标识符。如果内部指针为空,则返回一个值为 0 的空 GUID。 + +**参数:** 无 + +**返回:** 资源的 `ResourceGUID`,如果句柄为空则返回 `ResourceGUID(0)` + +**复杂度:** O(1) + +**示例:** + +```cpp +ResourceHandle tex = ResourceManager::Get().Load("tex.png"); +ResourceGUID guid = tex.GetGUID(); +if (guid.IsValid()) { + printf("GUID: %s\n", guid.ToString().CStr()); +} +``` + +## 相关文档 + +- [ResourceHandle 总览](resourcehandle.md) - 返回类总览 diff --git a/docs/api/resources/resourcehandle/isvalid.md b/docs/api/resources/resourcehandle/isvalid.md new file mode 100644 index 0000000..0b2c1d2 --- /dev/null +++ b/docs/api/resources/resourcehandle/isvalid.md @@ -0,0 +1,29 @@ +# ResourceHandle::IsValid + +```cpp +bool IsValid() const +``` + +检查句柄是否持有有效资源。判断条件为:内部指针非空且资源的 `IsValid()` 返回 true。 + +**参数:** 无 + +**返回:** 如果持有有效资源则返回 true,否则返回 false + +**复杂度:** O(1) + +**示例:** + +```cpp +ResourceHandle tex = ResourceManager::Get().Load("tex.png"); +if (tex.IsValid()) { + // 安全访问资源 + tex->GenerateMipmaps(); +} else { + printf("Texture load failed!\n"); +} +``` + +## 相关文档 + +- [ResourceHandle 总览](resourcehandle.md) - 返回类总览 diff --git a/docs/api/resources/resourcehandle/reset.md b/docs/api/resources/resourcehandle/reset.md new file mode 100644 index 0000000..74f4484 --- /dev/null +++ b/docs/api/resources/resourcehandle/reset.md @@ -0,0 +1,31 @@ +# ResourceHandle::Reset + +```cpp +void Reset() +``` + +释放当前持有的资源引用。如果内部持有的资源指针非空,则调用 `ResourceManager::Release()` 减少引用计数,并将内部指针置为 `nullptr`。析构函数会自动调用此方法。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +ResourceHandle tex = ResourceManager::Get().Load("tex.png"); +// 使用纹理... +tex.Reset(); // 释放引用,引用计数 -1 + +// 或者让句柄离开作用域自动释放 +{ + ResourceHandle mesh = ResourceManager::Get().Load("model.fbx"); + // 使用网格... +} // mesh 自动 Reset() +``` + +## 相关文档 + +- [ResourceHandle 总览](resourcehandle.md) - 返回类总览 diff --git a/docs/api/resources/resourcehandle/resourcehandle.md b/docs/api/resources/resourcehandle/resourcehandle.md new file mode 100644 index 0000000..7a59b2c --- /dev/null +++ b/docs/api/resources/resourcehandle/resourcehandle.md @@ -0,0 +1,74 @@ +# ResourceHandle + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` (template) + +**描述**: 模板资源句柄类,提供资源的引用计数式安全访问,自动管理资源的加载和释放。 + +## 概述 + +`ResourceHandle` 是一个模板句柄类,用于安全地持有对资源的引用。它通过 `ResourceManager` 自动管理引用计数:当句柄被创建时引用计数增加,当句柄被销毁或调用 `Reset()` 时引用计数减少。这确保了资源在其仍被使用时不会被卸载。 + +## 模板参数 + +| 参数 | 约束 | 描述 | +|------|------|------| +| `T` | 必须派生自 `IResource` | 资源类型 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `ResourceHandle() = default` | 默认构造空句柄 | +| `explicit ResourceHandle(T* resource)` | 从裸指针构造(自动增加引用) | +| `ResourceHandle(const ResourceHandle& other)` | 拷贝构造(自动增加引用) | +| `ResourceHandle(ResourceHandle&& other) noexcept` | 移动构造 | +| `~ResourceHandle()` | 析构函数(自动调用 Reset) | +| `ResourceHandle& operator=(const ResourceHandle& other)` | 拷贝赋值(自动管理引用) | +| `ResourceHandle& operator=(ResourceHandle&& other) noexcept` | 移动赋值 | +| `T* Get() const` | 获取裸指针 | +| `T* operator->() const` | 通过指针访问资源成员 | +| `T& operator*() const` | 解引用获取资源引用 | +| `bool IsValid() const` | 检查句柄是否持有有效资源 | +| `explicit operator bool() const` | 隐式布尔转换 | +| `ResourceGUID GetGUID() const` | 获取资源的全局唯一标识符 | +| `ResourceType GetResourceType() const` | 获取资源类型 | +| `void Reset()` | 释放当前资源引用 | +| `void Swap(ResourceHandle& other)` | 交换两个句柄的内容 | + +## 比较运算 + +| 运算符 | 描述 | +|------|------| +| `operator==(ResourceHandle, ResourceHandle)` | 比较 GUID 是否相等 | +| `operator!=(ResourceHandle, ResourceHandle)` | 比较 GUID 是否不等 | + +## 使用示例 + +```cpp +// 加载资源(引用计数 +1) +ResourceHandle tex = ResourceManager::Get().Load("textures/player.png"); + +// 检查有效性 +if (tex.IsValid()) { + // 安全访问资源 + uint32_t width = tex->GetWidth(); +} + +// 拷贝句柄(引用计数 +1) +ResourceHandle tex2 = tex; + +// 移动句柄 +ResourceHandle tex3 = std::move(tex2); + +// 句柄离开作用域时自动释放(引用计数 -1) +tex.Reset(); // 手动释放 +``` + +## 相关文档 + +- [IResource](../iresource/iresource.md) - 资源基类 +- [ResourceManager](../resourcemanager/resourcemanager.md) - 资源管理器 +- [ResourceCache](../resourcecache/resourcecache.md) - 资源缓存 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/resourcehandle/swap.md b/docs/api/resources/resourcehandle/swap.md new file mode 100644 index 0000000..f41d772 --- /dev/null +++ b/docs/api/resources/resourcehandle/swap.md @@ -0,0 +1,30 @@ +# ResourceHandle::Swap + +```cpp +void Swap(ResourceHandle& other) +``` + +交换两个句柄持有的资源指针。使用 `std::swap` 交换内部指针,不会改变任何引用计数。此操作常用于在不影响引用计数的情况下安全地交换两个句柄的内容。 + +**参数:** +- `other` - 要交换的另一个 ResourceHandle 引用 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +ResourceHandle tex1 = ResourceManager::Get().Load("a.png"); +ResourceHandle tex2 = ResourceManager::Get().Load("b.png"); + +// 交换后 tex1 持有 b.png,tex2 持有 a.png +tex1.Swap(tex2); + +// 引用计数不变 +``` + +## 相关文档 + +- [ResourceHandle 总览](resourcehandle.md) - 返回类总览 diff --git a/docs/api/resources/resourcemanager/exists.md b/docs/api/resources/resourcemanager/exists.md new file mode 100644 index 0000000..13e0090 --- /dev/null +++ b/docs/api/resources/resourcemanager/exists.md @@ -0,0 +1,28 @@ +# ResourceManager::Exists + +```cpp +bool Exists(const Containers::String& path) const +bool Exists(ResourceGUID guid) const +``` + +检查资源是否已加载。 + +**参数:** +- `path` - 资源路径 +- `guid` - 资源全局唯一标识符 + +**返回:** 如果资源在缓存中则返回 true + +**复杂度:** O(1) + +**示例:** + +```cpp +if (ResourceManager::Get().Exists("textures/player.png")) { + auto tex = ResourceManager::Get().Load("textures/player.png"); +} +``` + +## 相关文档 + +- [ResourceManager 总览](resourcemanager.md) - 返回类总览 diff --git a/docs/api/resources/resourcemanager/find.md b/docs/api/resources/resourcemanager/find.md new file mode 100644 index 0000000..469f994 --- /dev/null +++ b/docs/api/resources/resourcemanager/find.md @@ -0,0 +1,29 @@ +# ResourceManager::Find + +```cpp +IResource* Find(const Containers::String& path) +IResource* Find(ResourceGUID guid) +``` + +在资源缓存中查找资源。返回裸指针,不增加引用计数。 + +**参数:** +- `path` - 资源路径 +- `guid` - 资源全局唯一标识符 + +**返回:** 找到则返回资源指针,否则返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +IResource* res = ResourceManager::Get().Find("textures/player.png"); +if (res && res->IsValid()) { + Texture* tex = static_cast(res); +} +``` + +## 相关文档 + +- [ResourceManager 总览](resourcemanager.md) - 返回类总览 diff --git a/docs/api/resources/resourcemanager/getloader.md b/docs/api/resources/resourcemanager/getloader.md new file mode 100644 index 0000000..255e6f4 --- /dev/null +++ b/docs/api/resources/resourcemanager/getloader.md @@ -0,0 +1,27 @@ +# ResourceManager::GetLoader + +```cpp +IResourceLoader* GetLoader(ResourceType type) const +``` + +获取指定类型的资源加载器。 + +**参数:** +- `type` - 资源类型 + +**返回:** 对应的加载器指针,未找到则返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +IResourceLoader* texLoader = ResourceManager::Get().GetLoader(ResourceType::Texture); +if (texLoader) { + auto extensions = texLoader->GetSupportedExtensions(); +} +``` + +## 相关文档 + +- [ResourceManager 总览](resourcemanager.md) - 返回类总览 diff --git a/docs/api/resources/resourcemanager/load.md b/docs/api/resources/resourcemanager/load.md new file mode 100644 index 0000000..83b65aa --- /dev/null +++ b/docs/api/resources/resourcemanager/load.md @@ -0,0 +1,32 @@ +# ResourceManager::Load + +```cpp +template +ResourceHandle Load(const Containers::String& path, ImportSettings* settings = nullptr) +``` + +同步加载资源。模板方法,根据路径生成 GUID,先在缓存中查找是否已加载;若未加载则查找对应类型的加载器并同步加载,然后将结果加入缓存。 + +**参数:** +- `path` - 资源路径 +- `settings` - 导入设置(可选) + +**返回:** `ResourceHandle`,持有加载的资源 + +**复杂度:** O(n),取决于加载器实现 + +**示例:** + +```cpp +ResourceHandle tex = ResourceManager::Get().Load("textures/player.png"); +ResourceHandle mesh = ResourceManager::Get().Load("models/player.fbx"); +ResourceHandle mat = ResourceManager::Get().Load("materials/player.mat"); + +if (tex.IsValid()) { + // 使用纹理... +} +``` + +## 相关文档 + +- [ResourceManager 总览](resourcemanager.md) - 返回类总览 diff --git a/docs/api/resources/resourcemanager/loadasync.md b/docs/api/resources/resourcemanager/loadasync.md new file mode 100644 index 0000000..7c47081 --- /dev/null +++ b/docs/api/resources/resourcemanager/loadasync.md @@ -0,0 +1,44 @@ +# ResourceManager::LoadAsync + +```cpp +void LoadAsync(const Containers::String& path, ResourceType type, + std::function callback) +void LoadAsync(const Containers::String& path, ResourceType type, + ImportSettings* settings, std::function callback) +``` + +异步加载资源。将加载请求提交到 `AsyncLoader`,在后台工作线程执行加载,完成后在主线程通过回调通知。 + +**参数:** +- `path` - 资源路径 +- `type` - 资源类型 +- `settings` - 导入设置(可为 nullptr) +- `callback` - 加载完成回调 + +**返回:** 无 + +**复杂度:** 提交 O(1),实际加载 O(n) + +**示例:** + +```cpp +ResourceManager::Get().LoadAsync("textures/terrain.png", ResourceType::Texture, + [](LoadResult result) { + if (result.success) { + ResourceHandle tex(result.resource); + printf("Loaded: %s\n", tex->GetPath().CStr()); + } + }); + +ResourceManager::Get().LoadAsync("models/player.fbx", ResourceType::Mesh, + nullptr, + [](LoadResult result) { + if (result.success) { + ResourceHandle mesh(result.resource); + } + }); +``` + +## 相关文档 + +- [ResourceManager 总览](resourcemanager.md) - 返回类总览 diff --git a/docs/api/resources/resourcemanager/loadgroup.md b/docs/api/resources/resourcemanager/loadgroup.md new file mode 100644 index 0000000..23193e5 --- /dev/null +++ b/docs/api/resources/resourcemanager/loadgroup.md @@ -0,0 +1,35 @@ +# ResourceManager::LoadGroup + +```cpp +template +void LoadGroup(const Containers::Array& paths, + std::function)> callback) +``` + +批量异步加载同类资源。为路径数组中的每个路径提交一个异步加载请求,所有加载完成时通过回调通知。 + +**参数:** +- `paths` - 资源路径数组 +- `callback` - 每个资源加载完成时的回调 + +**返回:** 无 + +**复杂度:** O(k),k 为路径数量(每个加载为 O(n)) + +**示例:** + +```cpp +Containers::Array texPaths = { + "textures/a.png", "textures/b.png", "textures/c.png" +}; +ResourceManager::Get().LoadGroup(texPaths, + [](ResourceHandle tex) { + if (tex.IsValid()) { + printf("Loaded: %s\n", tex->GetPath().CStr()); + } + }); +``` + +## 相关文档 + +- [ResourceManager 总览](resourcemanager.md) - 返回类总览 diff --git a/docs/api/resources/resourcemanager/registerloader.md b/docs/api/resources/resourcemanager/registerloader.md new file mode 100644 index 0000000..62c01cc --- /dev/null +++ b/docs/api/resources/resourcemanager/registerloader.md @@ -0,0 +1,26 @@ +# ResourceManager::RegisterLoader + +```cpp +void RegisterLoader(IResourceLoader* loader) +``` + +注册资源加载器。管理器持有加载器指针所有权。 + +**参数:** +- `loader` - 加载器实例指针 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +ResourceManager::Get().RegisterLoader(new TextureLoader()); +ResourceManager::Get().RegisterLoader(new MeshLoader()); +ResourceManager::Get().RegisterLoader(new MaterialLoader()); +``` + +## 相关文档 + +- [ResourceManager 总览](resourcemanager.md) - 返回类总览 diff --git a/docs/api/resources/resourcemanager/resourcemanager.md b/docs/api/resources/resourcemanager/resourcemanager.md new file mode 100644 index 0000000..97921f4 --- /dev/null +++ b/docs/api/resources/resourcemanager/resourcemanager.md @@ -0,0 +1,101 @@ +# ResourceManager + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` (singleton) + +**描述**: 资源管理器单例,负责资源的加载、缓存、引用计数管理和异步加载调度。 + +## 概述 + +`ResourceManager` 是 XCEngine 资源管理系统的核心单例类。它提供统一的资源加载接口、自动缓存管理、引用计数跟踪和异步加载支持。所有资源访问都应通过 `ResourceManager` 进行。 + +## 单例访问 + +| 方法 | 描述 | +|------|------| +| `static ResourceManager& Get()` | 获取单例实例 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `void Initialize()` | 初始化资源管理器 | +| `void Shutdown()` | 关闭资源管理器,卸载所有资源 | +| `void SetResourceRoot(const Containers::String& rootPath)` | 设置资源根目录 | +| `const Containers::String& GetResourceRoot() const` | 获取资源根目录 | +| `ResourceHandle Load(const Containers::String& path, ImportSettings* settings = nullptr)` | 同步加载资源(模板方法) | +| `void LoadAsync(const Containers::String& path, ResourceType type, std::function callback)` | 异步加载资源 | +| `void LoadAsync(const Containers::String& path, ResourceType type, ImportSettings* settings, std::function callback)` | 带设置的异步加载 | +| `void LoadGroup(const Containers::Array& paths, std::function)> callback)` | 批量异步加载同类资源 | +| `void Unload(const Containers::String& path)` | 按路径卸载资源 | +| `void Unload(ResourceGUID guid)` | 按 GUID 卸载资源 | +| `void UnloadUnused()` | 卸载所有无引用的资源 | +| `void UnloadAll()` | 卸载所有资源 | +| `void AddRef(ResourceGUID guid)` | 增加引用计数(内部使用) | +| `void Release(ResourceGUID guid)` | 减少引用计数(内部使用) | +| `Core::uint32 GetRefCount(ResourceGUID guid) const` | 获取引用计数 | +| `IResource* Find(const Containers::String& path)` | 按路径查找资源 | +| `IResource* Find(ResourceGUID guid)` | 按 GUID 查找资源 | +| `bool Exists(const Containers::String& path) const` | 检查资源是否存在 | +| `bool Exists(ResourceGUID guid) const` | 检查 GUID 对应资源是否存在 | +| `void RegisterLoader(IResourceLoader* loader)` | 注册资源加载器 | +| `void UnregisterLoader(ResourceType type)` | 注销加载器 | +| `IResourceLoader* GetLoader(ResourceType type) const` | 获取指定类型的加载器 | +| `void SetMemoryBudget(size_t bytes)` | 设置内存预算 | +| `size_t GetMemoryUsage() const` | 获取当前内存使用量 | +| `size_t GetMemoryBudget() const` | 获取内存预算 | +| `void FlushCache()` | 清空缓存 | +| `Containers::String ResolvePath(const Containers::String& relativePath) const` | 将相对路径解析为绝对路径 | +| `Containers::Array GetResourcePaths() const` | 获取所有已加载资源的路径列表 | +| `void UnloadGroup(const Containers::Array& guids)` | 按 GUID 批量卸载 | + +## 实现说明 + +```cpp +// 初始化 +ResourceManager::Get().Initialize(); +ResourceManager::Get().SetResourceRoot("resources/"); + +// 注册加载器 +ResourceManager::Get().RegisterLoader(new TextureLoader()); +ResourceManager::Get().RegisterLoader(new MeshLoader()); +ResourceManager::Get().RegisterLoader(new MaterialLoader()); + +// 同步加载 +ResourceHandle tex = ResourceManager::Get().Load("textures/player.png"); +ResourceHandle mesh = ResourceManager::Get().Load("models/player.fbx"); + +// 异步加载 +ResourceManager::Get().LoadAsync("textures/terrain.png", ResourceType::Texture, + [](LoadResult result) { + if (result.success) { + ResourceHandle tex(result.resource); + // 使用纹理... + } + }); + +// 批量加载 +Containers::Array paths = {"a.png", "b.png", "c.png"}; +ResourceManager::Get().LoadGroup(paths, + [](ResourceHandle tex) { + if (tex.IsValid()) { + // 处理加载完成的纹理... + } + }); + +// 设置内存预算 +ResourceManager::Get().SetMemoryBudget(1024 * 1024 * 1024); // 1GB + +// 卸载 +ResourceManager::Get().UnloadUnused(); +ResourceManager::Get().Shutdown(); +``` + +## 相关文档 + +- [IResource](../iresource/iresource.md) - 资源基类 +- [ResourceHandle](../resourcehandle/resourcehandle.md) - 资源句柄 +- [ResourceCache](../resourcecache/resourcecache.md) - 资源缓存 +- [AsyncLoader](../asyncloader/asyncloader.md) - 异步加载器 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/resourcemanager/setmemorybudget.md b/docs/api/resources/resourcemanager/setmemorybudget.md new file mode 100644 index 0000000..6d790ba --- /dev/null +++ b/docs/api/resources/resourcemanager/setmemorybudget.md @@ -0,0 +1,24 @@ +# ResourceManager::SetMemoryBudget + +```cpp +void SetMemoryBudget(size_t bytes) +``` + +设置资源管理的内存预算上限。当缓存中资源的总内存占用超过预算时,会触发 LRU 驱逐策略释放内存。 + +**参数:** +- `bytes` - 内存预算大小(字节) + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +ResourceManager::Get().SetMemoryBudget(1024 * 1024 * 1024); // 1GB 预算 +``` + +## 相关文档 + +- [ResourceManager 总览](resourcemanager.md) - 返回类总览 diff --git a/docs/api/resources/resourcemanager/unload.md b/docs/api/resources/resourcemanager/unload.md new file mode 100644 index 0000000..8eea6d9 --- /dev/null +++ b/docs/api/resources/resourcemanager/unload.md @@ -0,0 +1,31 @@ +# ResourceManager::Unload + +```cpp +void Unload(const Containers::String& path) +void Unload(ResourceGUID guid) +``` + +卸载指定资源。按路径或 GUID 查找资源,如果引用计数降至零则释放资源内存。 + +**参数:** +- `path` - 资源路径 +- `guid` - 资源全局唯一标识符 + +**返回:** 无 + +**复杂度:** O(1) 查找 + +**示例:** + +```cpp +// 按路径卸载 +ResourceManager::Get().Unload("textures/player.png"); + +// 按 GUID 卸载 +ResourceGUID guid = tex.GetGUID(); +ResourceManager::Get().Unload(guid); +``` + +## 相关文档 + +- [ResourceManager 总览](resourcemanager.md) - 返回类总览 diff --git a/docs/api/resources/resourcemanager/unloadunused.md b/docs/api/resources/resourcemanager/unloadunused.md new file mode 100644 index 0000000..27bcb76 --- /dev/null +++ b/docs/api/resources/resourcemanager/unloadunused.md @@ -0,0 +1,26 @@ +# ResourceManager::UnloadUnused + +```cpp +void UnloadUnused() +``` + +卸载所有无引用的资源。遍历资源缓存,将引用计数为零的资源全部释放。常在场景切换或内存紧张时调用。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n) + +**示例:** + +```cpp +// 切换场景时清理无用资源 +void OnSceneUnload() { + ResourceManager::Get().UnloadUnused(); +} +``` + +## 相关文档 + +- [ResourceManager 总览](resourcemanager.md) - 返回类总览 diff --git a/docs/api/resources/resourcepackage/resourcepackage.md b/docs/api/resources/resourcepackage/resourcepackage.md new file mode 100644 index 0000000..8afc1f8 --- /dev/null +++ b/docs/api/resources/resourcepackage/resourcepackage.md @@ -0,0 +1,161 @@ +# ResourcePackage + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` + +**描述**: 资源包读写工具,支持打包多个资源文件到单个包文件中,以及从包中读取资源。 + +## 概述 + +`ResourcePackage` 提供了资源打包功能,可以将多个资源文件打包成单个包文件,方便分发和加载。包文件包含文件清单和数据区域。 + +## 头文件 + +```cpp +#include +``` + +--- + +## PackageFileEntry 结构体 + +打包文件条目信息。 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `relativePath` | `Containers::String` | 相对路径 | +| `size` | `size_t` | 文件大小 | +| `checksum` | `Core::uint64` | 校验和 | +| `offset` | `size_t` | 数据偏移量 | + +--- + +## ResourcePackageBuilder + +资源包构建器,用于创建新的资源包。 + +### 构造与析构 + +| 方法 | 描述 | +|------|------| +| `ResourcePackageBuilder()` | 默认构造 | +| `~ResourcePackageBuilder()` | 析构函数 | + +### 包构建 + +| 方法 | 描述 | +|------|------| +| `bool AddFile(const Containers::String& sourcePath, const Containers::String& relativePath)` | 添加单个文件到包 | +| `bool AddDirectory(const Containers::String& sourceDir, const Containers::String& relativeBase = "")` | 添加整个目录到包(当前为 stub,始终返回 true) | +| `void SetOutputPath(const Containers::String& path)` | 设置输出包文件路径 | +| `const Containers::String& GetOutputPath() const` | 获取输出路径 | +| `bool Build()` | 构建包文件 | +| `float GetProgress() const` | 获取构建进度(0.0f ~ 1.0f) | +| `const Containers::String& GetError() const` | 获取错误信息 | + +## 实现说明 + +**注意**: `ResourcePackageBuilder::AddDirectory()` 当前为 stub,始终返回 true。 + +## 使用示例(构建) + +```cpp +ResourcePackageBuilder builder; + +// 添加文件 +builder.AddFile("textures/player.png", "textures/player.png"); +builder.AddFile("textures/terrain.png", "textures/terrain.png"); + +// 添加目录 +builder.AddDirectory("shaders/", "shaders/"); + +// 设置输出 +builder.SetOutputPath("data/resources.pkg"); + +// 构建 +if (builder.Build()) { + printf("Package built successfully!\n"); +} else { + printf("Build failed: %s\n", builder.GetError().CStr()); +} +``` + +--- + +## ResourcePackage + +资源包读取器,用于从已打包的文件中读取资源。 + +### 构造与析构 + +| 方法 | 描述 | +|------|------| +| `ResourcePackage()` | 默认构造 | +| `~ResourcePackage()` | 析构函数,自动关闭包 | + +### 包操作 + +| 方法 | 描述 | +|------|------| +| `bool Open(const Containers::String& packagePath)` | 打开包文件 | +| `void Close()` | 关闭包文件 | +| `bool IsValid() const` | 检查包是否有效 | + +### 文件操作 + +| 方法 | 描述 | +|------|------| +| `bool Exists(const Containers::String& relativePath) const` | 检查文件是否存在于包中 | +| `Containers::Array Read(const Containers::String& relativePath) const` | 读取包内文件 | +| `size_t GetSize(const Containers::String& relativePath) const` | 获取包内文件大小 | +| `void Enumerate(const Containers::String& pattern, Containers::Array& outFiles) const` | 枚举包内匹配的文件 | + +### 包信息 + +| 方法 | 描述 | +|------|------| +| `const PackageInfo& GetInfo() const` | 获取包信息 | + +### PackageInfo 结构体 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `path` | `Containers::String` | 包文件路径 | +| `version` | `Core::uint16` | 包格式版本 | +| `fileCount` | `size_t` | 文件数量 | +| `totalSize` | `size_t` | 总大小 | + +## 使用示例(读取) + +```cpp +ResourcePackage package; +if (package.Open("data/resources.pkg")) { + // 检查文件 + if (package.Exists("textures/player.png")) { + // 读取文件 + auto data = package.Read("textures/player.png"); + if (!data.Empty()) { + // 使用数据... + } + } + + // 获取文件大小 + size_t size = package.GetSize("textures/player.png"); + + // 枚举文件 + Containers::Array files; + package.Enumerate("textures/*.png", files); + + // 获取包信息 + auto info = package.GetInfo(); + printf("Package: %s, Files: %zu\n", info.path.CStr(), info.fileCount); + + package.Close(); +} +``` + +## 相关文档 + +- [ResourceFileSystem](../filesystem/filesystem.md) - 资源文件系统 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/resourcepath/resourcepath.md b/docs/api/resources/resourcepath/resourcepath.md new file mode 100644 index 0000000..daf71b0 --- /dev/null +++ b/docs/api/resources/resourcepath/resourcepath.md @@ -0,0 +1,87 @@ +# ResourcePath + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` + +**描述**: 资源路径封装类,提供路径解析、转换和 GUID 生成功能。 + +## 概述 + +`ResourcePath` 封装了资源路径字符串,提供了一系列便捷方法进行路径解析、扩展名检查和 GUID 转换。 + +## 头文件 + +```cpp +#include +``` + +## 公共方法 + +### 构造 + +| 方法 | 描述 | +|------|------| +| `ResourcePath() = default` | 默认构造空路径 | +| `ResourcePath(const char* path)` | 从 C 字符串构造 | +| `ResourcePath(const Containers::String& path)` | 从 String 构造 | + +### 路径解析 + +| 方法 | 描述 | +|------|------| +| `Containers::String GetExtension() const` | 获取文件扩展名 | +| `Containers::String GetStem() const` | 获取文件名(不含扩展名) | +| `Containers::String GetFullPath() const` | 获取完整路径 | +| `Containers::String GetFileName() const` | 获取文件名(含扩展名) | +| `Containers::String GetDirectory() const` | 获取目录部分 | +| `Containers::String GetRelativePath() const` | 获取相对路径 | + +### GUID 转换 + +| 方法 | 描述 | +|------|------| +| `ResourceGUID ToGUID() const` | 将路径转换为 GUID | + +### 扩展名检查 + +| 方法 | 描述 | +|------|------| +| `bool HasExtension(const char* ext) const` | 检查是否具有指定扩展名 | +| `bool HasAnyExtension(const char* const* extensions, Core::uint32 count) const` | 检查是否具有任意指定扩展名 | + +### 状态 + +| 方法 | 描述 | +|------|------| +| `bool IsValid() const` | 检查路径是否有效(非空) | +| `const Containers::String& GetPath() const` | 获取原始路径字符串 | +| `void SetPath(const Containers::String& path)` | 设置路径字符串 | + +## 使用示例 + +```cpp +ResourcePath path("textures/player.png"); + +// 路径解析 +Containers::String ext = path.GetExtension(); // ".png" +Containers::String name = path.GetFileName(); // "player.png" +Containers::String dir = path.GetDirectory(); // "textures" + +// 扩展名检查 +if (path.HasExtension(".png") || path.HasExtension(".jpg")) { + // 是图像文件 +} + +// 转换为 GUID +ResourceGUID guid = path.ToGUID(); + +// 在 HashMap 中作为键使用 +Containers::HashMap> textures; +``` + +## 相关文档 + +- [ResourceTypes](../resourcetypes/resourcetypes.md) - 资源类型定义 +- [ResourceManager](../resourcemanager/resourcemanager.md) - 资源管理器 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/resources.md b/docs/api/resources/resources.md new file mode 100644 index 0000000..fc28c9c --- /dev/null +++ b/docs/api/resources/resources.md @@ -0,0 +1,95 @@ +# Resources 模块概览 + +**命名空间**: `XCEngine::Resources` + +**类型**: `module` + +**描述**: XCEngine 的资源管理系统,提供资源的异步加载、缓存和依赖管理。 + +## 概述 + +Resources 模块提供了一套完整的资源管理解决方案,支持同步和异步加载、资源缓存、依赖图管理等功能。 + +## 模块内容 + +### 核心组件 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [IResource](iresource/iresource.md) | `IResource.h` | 资源基类 | +| [ResourceHandle](resourcehandle/resourcehandle.md) | `ResourceHandle.h` | 资源句柄模板 | +| [IResourceLoader](iloader/iloader.md) | `IResourceLoader.h` | 资源加载器接口 | +| [ResourceManager](resourcemanager/resourcemanager.md) | `ResourceManager.h` | 资源管理器 | +| [ResourceCache](resourcecache/resourcecache.md) | `ResourceCache.h` | 资源缓存 | +| [AsyncLoader](asyncloader/asyncloader.md) | `AsyncLoader.h` | 异步加载器 | +| [ResourceDependencyGraph](dependencygraph/dependencygraph.md) | `ResourceDependencyGraph.h` | 依赖图 | +| [ResourceTypes](resourcetypes/resourcetypes.md) | `ResourceTypes.h` | 资源类型定义 | +| [ResourcePath](resourcepath/resourcepath.md) | `ResourcePath.h` | 资源路径封装 | +| [ResourceFileSystem](filesystem/filesystem.md) | `ResourceFileSystem.h` | 虚拟文件系统 | +| [ImportSettings](importsettings/importsettings.md) | `ImportSettings.h` | 导入设置基类 | + +### 文件与打包 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [FileArchive](filearchive/filearchive.md) | `FileArchive.h` | 文件归档读取 | +| [ResourcePackage](resourcepackage/resourcepackage.md) | `ResourcePackage.h` | 资源包打包/读取 | + +### 具体资源类型 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [Texture](texture/texture.md) | `Texture.h` | 纹理资源 | +| [Mesh](mesh/mesh.md) | `Mesh.h` | 网格资源 | +| [Material](material/material.md) | `Material.h` | 材质资源 | +| [Shader](shader/shader.md) | `Shader.h` | 着色器资源 | +| [AudioClip](audioclip/audioclip.md) | `AudioClip.h` | 音频资源 | + +## 资源类型 + +| 类型 | 描述 | +|------|------| +| `Texture` | 纹理资源 | +| `Mesh` | 网格/模型资源 | +| `Material` | 材质资源 | +| `Shader` | 着色器资源 | +| `AudioClip` | 音频资源 | +| `Binary` | 二进制数据 | +| `AnimationClip` | 动画片段 | +| `Skeleton` | 骨骼 | +| `Font` | 字体 | +| `ParticleSystem` | 粒子系统 | +| `Scene` | 场景 | +| `Prefab` | 预制体 | + +## 使用示例 + +```cpp +#include + +// 初始化资源管理器 +ResourceManager::Get().Initialize(); +ResourceManager::Get().SetResourceRoot("resources/"); + +// 同步加载资源 +ResourceHandle tex = ResourceManager::Get().Load("textures/player.png"); +ResourceHandle mesh = ResourceManager::Get().Load("models/player.fbx"); +ResourceHandle mat = ResourceManager::Get().Load("materials/player.mat"); + +// 异步加载 +ResourceManager::Get().LoadAsync("textures/terrain.png", ResourceType::Texture, + [](LoadResult result) { + if (result.success) { + ResourceHandle tex(result.resource); + // 加载完成回调 + } + }); + +// 释放资源 +tex.Reset(); +mesh.Reset(); +``` + +## 相关文档 + +- [RHI 模块](../rhi/rhi.md) - GPU 资源创建 diff --git a/docs/api/resources/resourcetypes/generate.md b/docs/api/resources/resourcetypes/generate.md new file mode 100644 index 0000000..e41bc23 --- /dev/null +++ b/docs/api/resources/resourcetypes/generate.md @@ -0,0 +1,26 @@ +# ResourceGUID::Generate + +```cpp +static ResourceGUID Generate(const char* path) +static ResourceGUID Generate(const Containers::String& path) +``` + +从资源路径生成唯一的全局标识符。通过哈希算法将路径字符串转换为唯一的 64 位整数。 + +**参数:** +- `path` - 资源路径 + +**返回:** 生成的 `ResourceGUID` + +**复杂度:** O(n) + +**示例:** + +```cpp +ResourceGUID guid = ResourceGUID::Generate("textures/player.png"); +ResourceGUID guid2 = ResourceGUID::Generate("models/player.fbx"); +``` + +## 相关文档 + +- [ResourceTypes 总览](resourcetypes.md) - 返回类总览 diff --git a/docs/api/resources/resourcetypes/getresourcetypename.md b/docs/api/resources/resourcetypes/getresourcetypename.md new file mode 100644 index 0000000..7a57e27 --- /dev/null +++ b/docs/api/resources/resourcetypes/getresourcetypename.md @@ -0,0 +1,25 @@ +# GetResourceTypeName + +```cpp +constexpr const char* GetResourceTypeName(ResourceType type) +``` + +获取资源类型的字符串名称。通过 switch 语句返回对应的类型名字符串。 + +**参数:** +- `type` - 资源类型枚举值 + +**返回:** 类型名字符串(如 `"Texture"`、`"Mesh"` 等) + +**复杂度:** O(1) + +**示例:** + +```cpp +const char* name = GetResourceTypeName(ResourceType::Texture); // "Texture" +const char* name2 = GetResourceTypeName(ResourceType::Shader); // "Shader" +``` + +## 相关文档 + +- [ResourceTypes 总览](resourcetypes.md) - 返回类总览 diff --git a/docs/api/resources/resourcetypes/resourcetypes.md b/docs/api/resources/resourcetypes/resourcetypes.md new file mode 100644 index 0000000..5cf14a0 --- /dev/null +++ b/docs/api/resources/resourcetypes/resourcetypes.md @@ -0,0 +1,130 @@ +# ResourceTypes + +**命名空间**: `XCEngine::Resources` + +**类型**: `enums` / `structs` + +**描述**: 资源模块中使用的所有类型定义,包括资源类型枚举、GUID 结构体等。 + +## 概述 + +本文档汇总了 Resources 模块中的所有类型定义,包括资源类型枚举、GUID 结构体等基础类型。 + +--- + +## ResourceType + +资源类型枚举。 + +| 值 | 描述 | +|----|------| +| `Unknown` | 未知类型 | +| `Texture` | 纹理资源 | +| `Mesh` | 网格/模型资源 | +| `Material` | 材质资源 | +| `Shader` | 着色器资源 | +| `AudioClip` | 音频资源 | +| `Binary` | 二进制数据 | +| `AnimationClip` | 动画片段 | +| `Skeleton` | 骨骼 | +| `Font` | 字体 | +| `ParticleSystem` | 粒子系统 | +| `Scene` | 场景 | +| `Prefab` | 预制体 | + +--- + +## ResourceGUID + +全局唯一标识符结构体,用于唯一标识每个资源。 + +```cpp +struct ResourceGUID { + Core::uint64 value; + + ResourceGUID() : value(0) {} + explicit ResourceGUID(Core::uint64 v) : value(v) {} + + bool IsValid() const { return value != 0; } + bool operator==(const ResourceGUID& other) const { return value == other.value; } + bool operator!=(const ResourceGUID& other) const { return value != other.value; } + + static ResourceGUID Generate(const char* path); + static ResourceGUID Generate(const Containers::String& path); + + Containers::String ToString() const; +}; +``` + +### 比较运算 + +| 运算符 | 描述 | +|------|------| +| `operator==(ResourceGUID, ResourceGUID)` | 判断相等 | +| `operator!=(ResourceGUID, ResourceGUID)` | 判断不等 | + +### 哈希支持 + +`ResourceGUID` 可作为 HashMap 的键使用(特化了 `std::hash`)。 + +### 静态方法 + +| 方法 | 描述 | +|------|------| +| `static ResourceGUID Generate(const char* path)` | 从资源路径生成唯一 GUID | +| `static ResourceGUID Generate(const Containers::String& path)` | 从资源路径生成唯一 GUID | +| `Containers::String ToString() const` | 转换为字符串 | + +### 辅助函数 + +| 函数 | 描述 | +|------|------| +| `constexpr const char* GetResourceTypeName(ResourceType type)` | 获取资源类型的字符串名称 | +| `ResourceGUID MakeResourceGUID(const char* path)` | 从路径生成 GUID 的辅助函数 | + +### 模板特化 + +```cpp +template<> inline ResourceType GetResourceType() { return ResourceType::Texture; } +template<> inline ResourceType GetResourceType() { return ResourceType::Mesh; } +template<> inline ResourceType GetResourceType() { return ResourceType::Material; } +template<> inline ResourceType GetResourceType() { return ResourceType::Shader; } +template<> inline ResourceType GetResourceType() { return ResourceType::AudioClip; } +template<> inline ResourceType GetResourceType() { return ResourceType::Binary; } +``` + +**注意**: `GetResourceType()` 是模板特化函数,用于在编译时获取资源类型。 + +## 使用示例 + +```cpp +// 使用 ResourceGUID +ResourceGUID texGuid = ResourceGUID::Generate("textures/player.png"); +ResourceGUID meshGuid = ResourceGUID::Generate("models/player.fbx"); + +// GUID 比较 +if (texGuid == meshGuid) { + // 相同资源 +} + +// 有效性检查 +if (texGuid.IsValid()) { + // GUID 有效 +} + +// 在 HashMap 中使用 +Containers::HashMap cache; +cache[texGuid] = texture; + +// 获取类型名称 +const char* name = GetResourceTypeName(ResourceType::Texture); // "Texture" + +// 使用模板获取类型 +ResourceType type = GetResourceType(); // ResourceType::Texture +``` + +## 相关文档 + +- [IResource](../iresource/iresource.md) - 资源基类 +- [ResourceManager](../resourcemanager/resourcemanager.md) - 资源管理器 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/shader/addattribute.md b/docs/api/resources/shader/addattribute.md new file mode 100644 index 0000000..b1d2312 --- /dev/null +++ b/docs/api/resources/shader/addattribute.md @@ -0,0 +1,29 @@ +# Shader::AddAttribute + +```cpp +void AddAttribute(const ShaderAttribute& attribute) +``` + +添加顶点属性描述。 + +**参数:** +- `attribute` - 属性描述结构体 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +ShaderAttribute attr; +attr.name = "position"; +attr.location = 0; +attr.size = sizeof(float) * 3; +attr.type = 0; +vs->AddAttribute(attr); +``` + +## 相关文档 + +- [Shader 总览](shader.md) - 返回类总览 diff --git a/docs/api/resources/shader/adduniform.md b/docs/api/resources/shader/adduniform.md new file mode 100644 index 0000000..21d0b5f --- /dev/null +++ b/docs/api/resources/shader/adduniform.md @@ -0,0 +1,29 @@ +# Shader::AddUniform + +```cpp +void AddUniform(const ShaderUniform& uniform) +``` + +添加 Uniform 变量描述。 + +**参数:** +- `uniform` - Uniform 描述结构体 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +ShaderUniform uniform; +uniform.name = "modelMatrix"; +uniform.location = 0; +uniform.size = sizeof(float) * 16; +uniform.type = 0; +vs->AddUniform(uniform); +``` + +## 相关文档 + +- [Shader 总览](shader.md) - 返回类总览 diff --git a/docs/api/resources/shader/shader.md b/docs/api/resources/shader/shader.md new file mode 100644 index 0000000..6caf6b5 --- /dev/null +++ b/docs/api/resources/shader/shader.md @@ -0,0 +1,154 @@ +# Shader + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` + +**描述**: 着色器资源类,管理着色器源码、编译后的二进制和 uniform/attribute 信息。 + +## 概述 + +`Shader` 是 XCEngine 中的着色器资源类,继承自 `IResource`。它管理着色器源码、编译后的二进制数据、着色器类型、语言类型、uniform 列表和 attribute 列表,并持有对应的 RHI 着色器资源指针。 + +## 头文件 + +```cpp +#include +``` + +## 枚举类型 + +### ShaderType + +着色器类型枚举。 + +| 值 | 描述 | +|----|------| +| `Vertex` | 顶点着色器 | +| `Fragment` | 片元着色器 | +| `Geometry` | 几何着色器 | +| `Compute` | 计算着色器 | +| `Hull` | Hull 着色器(曲面细分控制) | +| `Domain` | Domain 着色器(曲面细分评估) | + +### ShaderLanguage + +着色器语言枚举。 + +| 值 | 描述 | +|----|------| +| `GLSL` | OpenGL Shading Language | +| `HLSL` | High-Level Shading Language | +| `SPIRV` | SPIR-V 二进制格式 | + +## 结构体 + +### ShaderUniform + +Uniform 变量描述。 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `name` | `Containers::String` | Uniform 名称 | +| `location` | `Core::uint32` | 位置/绑定点 | +| `size` | `Core::uint32` | 大小(字节) | +| `type` | `Core::uint32` | 类型标识 | + +### ShaderAttribute + +顶点属性描述。 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `name` | `Containers::String` | 属性名称 | +| `location` | `Core::uint32` | 位置索引 | +| `size` | `Core::uint32` | 大小(字节) | +| `type` | `Core::uint32` | 类型标识 | + +## 公共方法 + +### 基础属性 + +| 方法 | 描述 | +|------|------| +| `ResourceType GetType() const` | 返回 `ResourceType::Shader` | +| `const Containers::String& GetName() const` | 获取着色器名称 | +| `const Containers::String& GetPath() const` | 获取着色器路径 | +| `ResourceGUID GetGUID() const` | 获取全局唯一标识符 | +| `bool IsValid() const` | 检查着色器是否有效 | +| `size_t GetMemorySize() const` | 获取内存大小 | +| `void Release()` | 释放着色器引用 | + +## 实现说明 + +**注意**: `ShaderLoader::DetectShaderType()` 对于非标准扩展名始终返回 `ShaderType::Fragment`。`ShaderLoader::ParseShaderSource()` 为 stub,始终返回 true。 + +### 类型与语言 + +| 方法 | 描述 | +|------|------| +| `void SetShaderType(ShaderType type)` | 设置着色器类型 | +| `ShaderType GetShaderType() const` | 获取着色器类型 | +| `void SetShaderLanguage(ShaderLanguage lang)` | 设置着色器语言 | +| `ShaderLanguage GetShaderLanguage() const` | 获取着色器语言 | + +### 源码与编译 + +| 方法 | 描述 | +|------|------| +| `void SetSourceCode(const Containers::String& source)` | 设置源码 | +| `const Containers::String& GetSourceCode() const` | 获取源码 | +| `void SetCompiledBinary(const Containers::Array& binary)` | 设置编译后二进制 | +| `const Containers::Array& GetCompiledBinary() const` | 获取编译后二进制 | + +### Uniform 和 Attribute + +| 方法 | 描述 | +|------|------| +| `void AddUniform(const ShaderUniform& uniform)` | 添加 Uniform 描述 | +| `const Containers::Array& GetUniforms() const` | 获取 Uniform 列表 | +| `void AddAttribute(const ShaderAttribute& attribute)` | 添加 Attribute 描述 | +| `const Containers::Array& GetAttributes() const` | 获取 Attribute 列表 | + +### RHI 资源 + +| 方法 | 描述 | +|------|------| +| `class IRHIShader* GetRHIResource() const` | 获取 RHI 着色器资源 | +| `void SetRHIResource(class IRHIShader* resource)` | 设置 RHI 着色器资源 | + +## 使用示例 + +```cpp +// 加载着色器 +ResourceHandle vs = ResourceManager::Get().Load("shaders/vertex.glsl"); +ResourceHandle fs = ResourceManager::Get().Load("shaders/fragment.glsl"); + +// 设置类型 +vs->SetShaderType(ShaderType::Vertex); +fs->SetShaderType(ShaderType::Fragment); + +// 设置语言 +vs->SetShaderLanguage(ShaderLanguage::GLSL); + +// 设置编译后二进制 +vs->SetCompiledBinary(compiledSpirv); + +// 添加 Uniform +ShaderUniform uniform; +uniform.name = "modelMatrix"; +uniform.location = 0; +uniform.size = sizeof(float) * 16; +uniform.type = 0; +vs->AddUniform(uniform); + +// 访问 RHI 资源 +RHIShader* rhiShader = vs->GetRHIResource(); +``` + +## 相关文档 + +- [IResource](../iresource/iresource.md) - 资源基类 +- [RHIShader](../../rhi/shader/shader.md) - RHI 着色器接口 +- [Material](../material/material.md) - 材质资源 +- [Resources 总览](../resources.md) - 返回模块总览 diff --git a/docs/api/resources/texture/create.md b/docs/api/resources/texture/create.md new file mode 100644 index 0000000..96f621f --- /dev/null +++ b/docs/api/resources/texture/create.md @@ -0,0 +1,39 @@ +# Texture::Create + +```cpp +bool Create(Core::uint32 width, Core::uint32 height, Core::uint32 depth, + Core::uint32 mipLevels, TextureType type, TextureFormat format, + const void* data, size_t dataSize) +``` + +创建纹理资源。设置纹理的尺寸、格式和像素数据,并分配 GPU 资源。 + +**参数:** +- `width` - 纹理宽度(像素) +- `height` - 纹理高度(像素) +- `depth` - 纹理深度(3D 纹理设为 1) +- `mipLevels` - Mipmap 级别数 +- `type` - 纹理类型 +- `format` - 纹理格式 +- `data` - 像素数据指针 +- `dataSize` - 像素数据大小 + +**返回:** 创建成功返回 true + +**复杂度:** O(n),n 为像素数量 + +**示例:** + +```cpp +Texture tex; +bool ok = tex.Create( + 1024, 1024, 1, 0, + TextureType::Texture2D, + TextureFormat::RGBA8_UNORM, + pixelData, pixelDataSize +); +``` + +## 相关文档 + +- [Texture 总览](texture.md) - 返回类总览 diff --git a/docs/api/resources/texture/generatemipmaps.md b/docs/api/resources/texture/generatemipmaps.md new file mode 100644 index 0000000..37a5164 --- /dev/null +++ b/docs/api/resources/texture/generatemipmaps.md @@ -0,0 +1,24 @@ +# Texture::GenerateMipmaps + +```cpp +bool GenerateMipmaps() +``` + +生成纹理的 Mipmap 链。根据基础级别纹理自动生成所有下采样级别,用于纹理在缩小渲染时避免闪烁。 + +**参数:** 无 + +**返回:** 生成成功返回 true + +**复杂度:** O(n) + +**示例:** + +```cpp +tex.Create(1024, 1024, 1, 1, TextureType::Texture2D, TextureFormat::RGBA8_UNORM, data, size); +tex.GenerateMipmaps(); +``` + +## 相关文档 + +- [Texture 总览](texture.md) - 返回类总览 diff --git a/docs/api/resources/texture/texture.md b/docs/api/resources/texture/texture.md new file mode 100644 index 0000000..1c8fa98 --- /dev/null +++ b/docs/api/resources/texture/texture.md @@ -0,0 +1,161 @@ +# Texture + +**命名空间**: `XCEngine::Resources` + +**类型**: `class` + +**描述**: 纹理资源类,管理 2D/3D 纹理和立方体贴图的像素数据。 + +## 概述 + +`Texture` 是 XCEngine 中的纹理资源类,继承自 `IResource`。它管理纹理的尺寸、格式、像素数据,并支持 mipmap 生成等功能。 + +## 头文件 + +```cpp +#include +``` + +## 枚举类型 + +### TextureType + +纹理类型枚举。 + +| 值 | 描述 | +|----|------| +| `Texture2D` | 2D 纹理 | +| `Texture3D` | 3D 体积纹理 | +| `TextureCube` | 立方体贴图 | +| `Texture2DArray` | 2D 纹理数组 | +| `TextureCubeArray` | 立方体贴图数组 | + +### TextureFormat + +纹理像素格式枚举。 + +| 值 | 描述 | +|----|------| +| `Unknown` | 未知格式 | +| `R8_UNORM` | 单通道 8 位归一化 | +| `RG8_UNORM` | 双通道 8 位归一化 | +| `RGBA8_UNORM` | 四通道 8 位归一化 | +| `RGBA8_SRGB` | 四通道 8 位 sRGB | +| `R16_FLOAT` | 单通道 16 位浮点 | +| `RG16_FLOAT` | 双通道 16 位浮点 | +| `RGBA16_FLOAT` | 四通道 16 位浮点 | +| `R32_FLOAT` | 单通道 32 位浮点 | +| `RG32_FLOAT` | 双通道 32 位浮点 | +| `RGBA32_FLOAT` | 四通道 32 位浮点 | +| `D16_UNORM` | 16 位深度 | +| `D24_UNORM_S8_UINT` | 24 位深度 + 8 位模板 | +| `D32_FLOAT` | 32 位深度 | +| `D32_FLOAT_S8_X24_UINT` | 32 位深度 + 8+24 位模板 | +| `BC1_UNORM` | BC1 压缩 (DXT1) | +| `BC1_UNORM_SRGB` | BC1 sRGB | +| `BC2_UNORM` | BC2 压缩 (DXT3) | +| `BC2_UNORM_SRGB` | BC2 sRGB | +| `BC3_UNORM` | BC3 压缩 (DXT5) | +| `BC3_UNORM_SRGB` | BC3 sRGB | +| `BC4_UNORM` | BC4 压缩 | +| `BC5_UNORM` | BC5 压缩 | +| `BC6H_UF16` | BC6H 压缩 | +| `BC7_UNORM` | BC7 压缩 | +| `BC7_UNORM_SRGB` | BC7 sRGB | + +### TextureUsage + +纹理用途标志枚举(可组合)。 + +| 值 | 描述 | +|----|------| +| `None` | 无特殊用途 | +| `ShaderResource` | 着色器资源 | +| `RenderTarget` | 渲染目标 | +| `DepthStencil` | 深度模板 | +| `UnorderedAccess` | 无序访问 | +| `TransferSrc` | 传输源 | +| `TransferDst` | 传输目标 | + +## 公共方法 + +### 基础属性 + +| 方法 | 描述 | +|------|------| +| `ResourceType GetType() const` | 返回 `ResourceType::Texture` | +| `const Containers::String& GetName() const` | 获取纹理名称 | +| `const Containers::String& GetPath() const` | 获取纹理路径 | +| `ResourceGUID GetGUID() const` | 获取全局唯一标识符 | +| `bool IsValid() const` | 检查纹理是否有效 | +| `size_t GetMemorySize() const` | 获取内存大小 | +| `void Release()` | 释放纹理引用 | + +### 纹理属性 + +| 方法 | 描述 | +|------|------| +| `Core::uint32 GetWidth() const` | 获取纹理宽度(像素) | +| `Core::uint32 GetHeight() const` | 获取纹理高度(像素) | +| `Core::uint32 GetDepth() const` | 获取纹理深度(3D 纹理) | +| `Core::uint32 GetMipLevels() const` | 获取 Mipmap 级别数 | +| `Core::uint32 GetArraySize() const` | 获取数组大小 | +| `TextureType GetTextureType() const` | 获取纹理类型 | +| `TextureFormat GetFormat() const` | 获取纹理格式 | +| `TextureUsage GetUsage() const` | 获取纹理用途标志 | + +### 像素数据 + +| 方法 | 描述 | +|------|------| +| `const void* GetPixelData() const` | 获取像素数据指针 | +| `size_t GetPixelDataSize() const` | 获取像素数据大小 | + +### 创建与操作 + +| 方法 | 描述 | +|------|------| +| `bool Create(Core::uint32 width, Core::uint32 height, Core::uint32 depth, Core::uint32 mipLevels, TextureType type, TextureFormat format, const void* data, size_t dataSize)` | 创建纹理 | +| `bool GenerateMipmaps()` | 生成 Mipmap(当前返回 false - stub) | + +## 实现说明 + +**注意**: `Create()` 方法中 `mipLevels` 参数为 0 时不会自动计算所有级别。`GenerateMipmaps()` 当前返回 false,为 stub 实现。 + +## 使用示例 + +```cpp +// 加载纹理 +ResourceHandle tex = ResourceManager::Get().Load("textures/player.png"); + +// 手动创建纹理 +Texture tex; +bool created = tex.Create( + 1024, // 宽度 + 1024, // 高度 + 1, // 深度 + 0, // Mipmap 级别(0=全部) + TextureType::Texture2D, // 类型 + TextureFormat::RGBA8_UNORM, // 格式 + pixelData, // 像素数据 + pixelDataSize // 数据大小 +); + +// 生成 Mipmap +tex.GenerateMipmaps(); + +// 访问纹理属性 +uint32_t w = tex.GetWidth(); +uint32_t h = tex.GetHeight(); +``` + +## 相关文档 + +- [IResource](../iresource/iresource.md) - 资源基类 +- [ResourceManager](../resourcemanager/resourcemanager.md) - 资源管理器 +- [RHITexture](../../rhi/texture/texture.md) - RHI 纹理接口 +- [Resources 总览](../resources.md) - 返回模块总览 + +## 实现说明 + +**注意**: `TextureLoader::Load()` 仅为示例实现,不解析 PNG/JPG 等格式的实际图像数据,仅创建空纹理对象。 diff --git a/docs/api/rhi/buffer/buffer.md b/docs/api/rhi/buffer/buffer.md new file mode 100644 index 0000000..1e774ef --- /dev/null +++ b/docs/api/rhi/buffer/buffer.md @@ -0,0 +1,86 @@ +# RHIBuffer + +**命名空间**: `XCEngine::RHI` + +**类型**: `class` (abstract) + +**描述**: GPU 缓冲区资源抽象接口,用于管理顶点缓冲、索引缓冲、常量缓冲等 GPU 内存资源。 + +## 概述 + +`RHIBuffer` 封装了 GPU 缓冲区的创建、数据上传、状态管理等操作。支持多种缓冲区类型,包括顶点缓冲、索引缓冲、常量缓冲等。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Map`](map.md) | 映射缓冲区到 CPU 可访问内存 | +| [`Unmap`](unmap.md) | 取消映射 | +| [`SetData`](set-data.md) | 设置缓冲区数据 | +| [`GetSize`](get-size.md) | 获取缓冲区大小 | +| [`GetBufferType`](get-buffer-type.md) | 获取缓冲区类型 | +| [`SetBufferType`](set-buffer-type.md) | 设置缓冲区类型 | +| [`GetStride`](get-stride.md) | 获取缓冲区步长 | +| [`SetStride`](set-stride.md) | 设置缓冲区步长 | +| [`GetState`](get-state.md) | 获取资源状态 | +| [`SetState`](set-state.md) | 设置资源状态 | +| [`Shutdown`](shutdown.md) | 关闭并释放资源 | +| [`GetNativeHandle`](get-native-handle.md) | 获取原生句柄 | +| [`GetName`](get-name.md) | 获取资源名称 | +| [`SetName`](set-name.md) | 设置资源名称 | + +## 缓冲区类型 (BufferType) + +| 枚举值 | 描述 | +|--------|------| +| `BufferType::Vertex` | 顶点缓冲 | +| `BufferType::Index` | 索引缓冲 | +| `BufferType::Constant` | 常量缓冲 (Constant Buffer) | +| `BufferType::ReadBack` | 回读缓冲(用于 CPU 读取 GPU 数据) | +| `BufferType::Indirect` | 间接执行缓冲 | +| `BufferType::RaytracingAccelerationStructure` | 光线追踪加速结构 | +| `BufferType::ShaderBindingTable` | 光线追踪着色器绑定表 | + +## 资源状态 (ResourceStates) + +| 状态 | 描述 | +|------|------| +| `Common` | 默认状态 | +| `VertexAndConstantBuffer` | 顶点/常量缓冲 | +| `IndexBuffer` | 索引缓冲 | +| `RenderTarget` | 渲染目标 | +| `UnorderedAccess` | 无序访问 | +| `DepthWrite` | 深度写入 | +| `DepthRead` | 深度读取 | +| `NonPixelShaderResource` | 非像素着色器资源 | +| `PixelShaderResource` | 像素着色器资源 | +| `CopySrc` | 复制源 | +| `CopyDst` | 复制目标 | +| `Present` | 呈现状态 | +| `GenericRead` | 通用读取 | + +## 使用示例 + +```cpp +BufferDesc desc; +desc.size = sizeof(Vertex) * vertexCount; +desc.stride = sizeof(Vertex); +desc.bufferType = (uint32_t)BufferType::Vertex; +desc.flags = 0; + +RHIBuffer* vertexBuffer = device->CreateBuffer(desc); + +void* mapped = vertexBuffer->Map(); +memcpy(mapped, vertexData, desc.size); +vertexBuffer->Unmap(); + +vertexBuffer->SetState(ResourceStates::VertexAndConstantBuffer); +vertexBuffer->Shutdown(); +``` + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHIDevice](../device/device.md) - 创建设备 +- [RHITexture](../texture/texture.md) - 纹理资源 +- [RHICommandList](../command-list/command-list.md) - 命令列表 diff --git a/docs/api/rhi/buffer/get-buffer-type.md b/docs/api/rhi/buffer/get-buffer-type.md new file mode 100644 index 0000000..df2d53f --- /dev/null +++ b/docs/api/rhi/buffer/get-buffer-type.md @@ -0,0 +1,15 @@ +# RHIBuffer::GetBufferType + +```cpp +virtual BufferType GetBufferType() const = 0; +``` + +获取缓冲区类型。 + +**返回:** 缓冲区类型枚举值 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/buffer/get-name.md b/docs/api/rhi/buffer/get-name.md new file mode 100644 index 0000000..749f53f --- /dev/null +++ b/docs/api/rhi/buffer/get-name.md @@ -0,0 +1,15 @@ +# RHIBuffer::GetName + +```cpp +virtual const std::string& GetName() const = 0; +``` + +获取缓冲区名称(用于调试)。 + +**返回:** 缓冲区名称 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/buffer/get-native-handle.md b/docs/api/rhi/buffer/get-native-handle.md new file mode 100644 index 0000000..dabc40f --- /dev/null +++ b/docs/api/rhi/buffer/get-native-handle.md @@ -0,0 +1,17 @@ +# RHIBuffer::GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 + +**返回:** +- D3D12: `ID3D12Resource*` +- OpenGL: `GLuint` 指针 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/buffer/get-size.md b/docs/api/rhi/buffer/get-size.md new file mode 100644 index 0000000..1e09922 --- /dev/null +++ b/docs/api/rhi/buffer/get-size.md @@ -0,0 +1,15 @@ +# RHIBuffer::GetSize + +```cpp +virtual uint64_t GetSize() const = 0; +``` + +获取缓冲区大小(字节)。 + +**返回:** 缓冲区大小 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/buffer/get-state.md b/docs/api/rhi/buffer/get-state.md new file mode 100644 index 0000000..c5818c8 --- /dev/null +++ b/docs/api/rhi/buffer/get-state.md @@ -0,0 +1,15 @@ +# RHIBuffer::GetState + +```cpp +virtual ResourceStates GetState() const = 0; +``` + +获取当前资源状态。 + +**返回:** 资源状态枚举值 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/buffer/get-stride.md b/docs/api/rhi/buffer/get-stride.md new file mode 100644 index 0000000..82b2982 --- /dev/null +++ b/docs/api/rhi/buffer/get-stride.md @@ -0,0 +1,15 @@ +# RHIBuffer::GetStride + +```cpp +virtual uint32_t GetStride() const = 0; +``` + +获取单个元素的字节大小。 + +**返回:** 元素步长(字节) + +**复杂度:** O(1) + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/buffer/map.md b/docs/api/rhi/buffer/map.md new file mode 100644 index 0000000..70ef5a7 --- /dev/null +++ b/docs/api/rhi/buffer/map.md @@ -0,0 +1,25 @@ +# RHIBuffer::Map + +```cpp +virtual void* Map() = 0; +``` + +映射缓冲区内存到 CPU 可访问空间。 + +**返回:** 指向缓冲区数据的指针 + +**复杂度:** O(1) + +**示例:** + +```cpp +void* data = buffer->Map(); +if (data) { + memcpy(data, vertexData, bufferSize); + buffer->Unmap(); +} +``` + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/buffer/set-buffer-type.md b/docs/api/rhi/buffer/set-buffer-type.md new file mode 100644 index 0000000..2541eb6 --- /dev/null +++ b/docs/api/rhi/buffer/set-buffer-type.md @@ -0,0 +1,16 @@ +# RHIBuffer::SetBufferType + +```cpp +virtual void SetBufferType(BufferType type) = 0; +``` + +设置缓冲区类型。 + +**参数:** +- `type` - 新的缓冲区类型 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/buffer/set-data.md b/docs/api/rhi/buffer/set-data.md new file mode 100644 index 0000000..4c390b5 --- /dev/null +++ b/docs/api/rhi/buffer/set-data.md @@ -0,0 +1,29 @@ +# RHIBuffer::SetData + +```cpp +virtual void SetData(const void* data, size_t size, size_t offset = 0) = 0; +``` + +设置缓冲区数据。 + +**参数:** +- `data` - 源数据指针 +- `size` - 数据大小(字节) +- `offset` - 缓冲区内的偏移量 + +**复杂度:** O(n) + +**示例:** + +```cpp +Vertex vertices[] = { + {0.0f, 0.5f, 0.0f}, + {0.5f, -0.5f, 0.0f}, + {-0.5f, -0.5f, 0.0f} +}; +buffer->SetData(vertices, sizeof(vertices), 0); +``` + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/buffer/set-name.md b/docs/api/rhi/buffer/set-name.md new file mode 100644 index 0000000..62d6a46 --- /dev/null +++ b/docs/api/rhi/buffer/set-name.md @@ -0,0 +1,22 @@ +# RHIBuffer::SetName + +```cpp +virtual void SetName(const std::string& name) = 0; +``` + +设置缓冲区名称(用于调试)。 + +**参数:** +- `name` - 新名称 + +**复杂度:** O(1) + +**示例:** + +```cpp +buffer->SetName("VertexBuffer_Main"); +``` + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/buffer/set-state.md b/docs/api/rhi/buffer/set-state.md new file mode 100644 index 0000000..6bc3eaa --- /dev/null +++ b/docs/api/rhi/buffer/set-state.md @@ -0,0 +1,22 @@ +# RHIBuffer::SetState + +```cpp +virtual void SetState(ResourceStates state) = 0; +``` + +设置资源状态。 + +**参数:** +- `state` - 新的资源状态 + +**复杂度:** O(1) + +**示例:** + +```cpp +buffer->SetState(ResourceStates::VertexAndConstantBuffer); +``` + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/buffer/set-stride.md b/docs/api/rhi/buffer/set-stride.md new file mode 100644 index 0000000..fea0931 --- /dev/null +++ b/docs/api/rhi/buffer/set-stride.md @@ -0,0 +1,16 @@ +# RHIBuffer::SetStride + +```cpp +virtual void SetStride(uint32_t stride) = 0; +``` + +设置元素字节大小。 + +**参数:** +- `stride` - 新的步长值 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/buffer/shutdown.md b/docs/api/rhi/buffer/shutdown.md new file mode 100644 index 0000000..568391e --- /dev/null +++ b/docs/api/rhi/buffer/shutdown.md @@ -0,0 +1,13 @@ +# RHIBuffer::Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +释放缓冲区资源。 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/buffer/unmap.md b/docs/api/rhi/buffer/unmap.md new file mode 100644 index 0000000..51b5bf9 --- /dev/null +++ b/docs/api/rhi/buffer/unmap.md @@ -0,0 +1,21 @@ +# RHIBuffer::Unmap + +```cpp +virtual void Unmap() = 0; +``` + +取消内存映射。 + +**复杂度:** O(1) + +**示例:** + +```cpp +buffer->Map(); +memcpy(mappedData, sourceData, size); +buffer->Unmap(); +``` + +## 相关文档 + +- [RHIBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/capabilities/capabilities.md b/docs/api/rhi/capabilities/capabilities.md new file mode 100644 index 0000000..4f67c35 --- /dev/null +++ b/docs/api/rhi/capabilities/capabilities.md @@ -0,0 +1,82 @@ +# RHICapabilities + +**命名空间**: `XCEngine::RHI` + +**类型**: `struct` + +**描述**: GPU 设备能力结构体,描述了当前图形设备支持的各种功能和限制。 + +## 公共成员 + +### 特性支持 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `bSupportsRayTracing` | `bool` | 支持光线追踪 | +| `bSupportsMeshShaders` | `bool` | 支持 Mesh 着色器 | +| `bSupportsExplicitMultiThreading` | `bool` | 支持显式多线程 | +| `bSupportsGeometryShaders` | `bool` | 支持几何着色器 | +| `bSupportsTessellation` | `bool` | 支持曲面细分 | +| `bSupportsComputeShaders` | `bool` | 支持计算着色器 | +| `bSupportsDepthBoundsTest` | `bool` | 支持深度范围测试 | +| `bSupportsAlphaToCoverage` | `bool` | 支持 Alpha 到覆盖 | +| `bSupportsIndependentBlend` | `bool` | 支持独立混合 | +| `bSupportsLogicOps` | `bool` | 支持逻辑操作 | +| `bSupportsMultiViewport` | `bool` | 支持多视口 | +| `bSupportsConservativeRasterization` | `bool` | 支持保守光栅化 | +| `bSupportsProgrammableSamplePositions` | `bool` | 支持可编程采样位置 | + +### 资源限制 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `maxTexture2DSize` | `uint32_t` | 最大 2D 纹理尺寸 | +| `maxTexture3DSize` | `uint32_t` | 最大 3D 纹理尺寸 | +| `maxTextureCubeSize` | `uint32_t` | 最大立方体贴图尺寸 | +| `maxRenderTargets` | `uint32_t` | 最大渲染目标数量 | +| `maxViewports` | `uint32_t` | 最大视口数量 | +| `maxVertexAttribs` | `uint32_t` | 最大顶点属性数量 | +| `maxConstantBufferSize` | `uint32_t` | 最大常量缓冲大小 | +| `maxAnisotropy` | `uint32_t` | 最大各向异性级别 | +| `maxColorAttachments` | `uint32_t` | 最大颜色附件数量 | + +### 线宽和点大小 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `minSmoothedLineWidth` | `float` | 最小平滑线宽 | +| `maxSmoothedLineWidth` | `float` | 最大平滑线宽 | +| `minPointSize` | `float` | 最小点大小 | +| `maxPointSize` | `float` | 最大点大小 | +| `maxPointSizeAA` | `float` | 抗锯齿最大点大小 | +| `maxLineWidth` | `float` | 最大线宽 | +| `maxLineWidthAA` | `float` | 抗锯齿最大线宽 | + +### 版本信息 + +| 成员 | 类型 | 描述 | +|------|------|------| +| `majorVersion` | `int` | 主版本号 | +| `minorVersion` | `int` | 次版本号 | +| `shaderModel` | `std::string` | 着色器模型版本 | + +## 使用示例 + +```cpp +const RHICapabilities& caps = device->GetCapabilities(); + +if (caps.bSupportsRayTracing) { + // 启用光线追踪功能 +} + +if (caps.bSupportsComputeShaders) { + // 启用计算着色器 +} + +uint32_t textureSize = std::min(requestedSize, caps.maxTexture2DSize); +``` + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHIDevice](../device/device.md) - 设备对象 diff --git a/docs/api/rhi/command-list/clear-depth-stencil.md b/docs/api/rhi/command-list/clear-depth-stencil.md new file mode 100644 index 0000000..e9e3492 --- /dev/null +++ b/docs/api/rhi/command-list/clear-depth-stencil.md @@ -0,0 +1,22 @@ +# RHICommandList::ClearDepthStencil + +```cpp +virtual void ClearDepthStencil(void* depthStencil, float depth, uint8_t stencil) = 0; +``` + +清除深度模板缓冲区。 + +**参数:** +- `depthStencil` - 深度模板缓冲区指针 +- `depth` - 深度值 +- `stencil` - 模板值 + +**示例:** + +```cpp +cmdList->ClearDepthStencil(depthStencil, 1.0f, 0); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/clear-render-target.md b/docs/api/rhi/command-list/clear-render-target.md new file mode 100644 index 0000000..2534b1d --- /dev/null +++ b/docs/api/rhi/command-list/clear-render-target.md @@ -0,0 +1,22 @@ +# RHICommandList::ClearRenderTarget + +```cpp +virtual void ClearRenderTarget(void* renderTarget, const float color[4]) = 0; +``` + +清除渲染目标。 + +**参数:** +- `renderTarget` - 渲染目标指针 +- `color` - 清除颜色 [r, g, b, a] + +**示例:** + +```cpp +float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; +cmdList->ClearRenderTarget(renderTarget, color); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/clear.md b/docs/api/rhi/command-list/clear.md new file mode 100644 index 0000000..f8307fc --- /dev/null +++ b/docs/api/rhi/command-list/clear.md @@ -0,0 +1,20 @@ +# RHICommandList::Clear + +```cpp +virtual void Clear(float r, float g, float b, float a, uint32_t buffers) = 0; +``` + +清除渲染目标。 + +**参数:** +- `r` - 红色分量 +- `g` - 绿色分量 +- `b` - 蓝色分量 +- `a` - Alpha 分量 +- `buffers` - 要清除的缓冲区标志 + +**复杂度:** O(1) + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/close.md b/docs/api/rhi/command-list/close.md new file mode 100644 index 0000000..ea2ee6e --- /dev/null +++ b/docs/api/rhi/command-list/close.md @@ -0,0 +1,13 @@ +# RHICommandList::Close + +```cpp +virtual void Close() = 0; +``` + +关闭命令列表以执行。 + +**复杂度:** O(1) + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/command-list.md b/docs/api/rhi/command-list/command-list.md new file mode 100644 index 0000000..8196d89 --- /dev/null +++ b/docs/api/rhi/command-list/command-list.md @@ -0,0 +1,55 @@ +# RHICommandList + +**命名空间**: `XCEngine::RHI` + +**类型**: `class` (abstract) + +**描述**: GPU 命令列表抽象接口,用于录制和执行 GPU 命令。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Reset`](reset.md) | 重置命令列表 | +| [`Close`](close.md) | 关闭命令列表 | +| [`TransitionBarrier`](transition-barrier.md) | 资源状态转换 | +| [`SetPipelineState`](set-pipeline-state.md) | 设置管线状态 | +| [`SetPrimitiveTopology`](set-primitive-topology.md) | 设置图元拓扑 | +| [`SetViewport`](set-viewport.md) | 设置视口 | +| [`SetViewports`](set-viewports.md) | 设置多个视口 | +| [`SetScissorRect`](set-scissor-rect.md) | 设置裁剪矩形 | +| [`SetScissorRects`](set-scissor-rects.md) | 设置多个裁剪矩形 | +| [`SetRenderTargets`](set-render-targets.md) | 设置渲染目标 | +| [`SetDepthStencilState`](set-depth-stencil-state.md) | 设置深度模板状态 | +| [`SetStencilRef`](set-stencil-ref.md) | 设置模板引用值 | +| [`SetBlendState`](set-blend-state.md) | 设置混合状态 | +| [`SetBlendFactor`](set-blend-factor.md) | 设置混合因子 | +| [`SetVertexBuffer`](set-vertex-buffer.md) | 设置顶点缓冲 | +| [`SetVertexBuffers`](set-vertex-buffers.md) | 设置多个顶点缓冲 | +| [`SetIndexBuffer`](set-index-buffer.md) | 设置索引缓冲 | +| [`Draw`](draw.md) | 绘制 | +| [`DrawIndexed`](draw-indexed.md) | 索引绘制 | +| [`Clear`](clear.md) | 清除 | +| [`ClearRenderTarget`](clear-render-target.md) | 清除渲染目标 | +| [`ClearDepthStencil`](clear-depth-stencil.md) | 清除深度模板 | +| [`CopyResource`](copy-resource.md) | 复制资源 | +| [`Dispatch`](dispatch.md) | 分发计算任务 | +| [`Shutdown`](shutdown.md) | 关闭并释放资源 | + +## 使用示例 + +```cpp +commandList->Reset(); +commandList->SetPipelineState(pipelineState); +commandList->SetPrimitiveTopology(PrimitiveTopology::TriangleList); +commandList->SetViewport(viewport); +commandList->SetRenderTargets(1, &renderTarget, depthStencil); +commandList->DrawIndexed(indexCount, 1, 0, 0, 0); +commandList->Close(); +commandQueue->ExecuteCommandLists(1, (void**)&commandList); +``` + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHICommandQueue](../command-queue/command-queue.md) - 命令队列 diff --git a/docs/api/rhi/command-list/copy-resource.md b/docs/api/rhi/command-list/copy-resource.md new file mode 100644 index 0000000..e1aa644 --- /dev/null +++ b/docs/api/rhi/command-list/copy-resource.md @@ -0,0 +1,21 @@ +# RHICommandList::CopyResource + +```cpp +virtual void CopyResource(void* dst, void* src) = 0; +``` + +复制资源。 + +**参数:** +- `dst` - 目标资源 +- `src` - 源资源 + +**示例:** + +```cpp +cmdList->CopyResource(dstTexture, srcTexture); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/dispatch.md b/docs/api/rhi/command-list/dispatch.md new file mode 100644 index 0000000..c1b24b5 --- /dev/null +++ b/docs/api/rhi/command-list/dispatch.md @@ -0,0 +1,22 @@ +# RHICommandList::Dispatch + +```cpp +virtual void Dispatch(uint32_t x, uint32_t y, uint32_t z) = 0; +``` + +分发计算着色器。 + +**参数:** +- `x` - X 方向线程组数量 +- `y` - Y 方向线程组数量 +- `z` - Z 方向线程组数量 + +**示例:** + +```cpp +cmdList->Dispatch(8, 8, 1); // 分发 8x8x1 线程组 +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/draw-indexed.md b/docs/api/rhi/command-list/draw-indexed.md new file mode 100644 index 0000000..1d7e5fa --- /dev/null +++ b/docs/api/rhi/command-list/draw-indexed.md @@ -0,0 +1,24 @@ +# RHICommandList::DrawIndexed + +```cpp +virtual void DrawIndexed(uint32_t indexCount, uint32_t instanceCount = 1, uint32_t startIndex = 0, int32_t baseVertex = 0, uint32_t startInstance = 0) = 0; +``` + +绘制索引图元。 + +**参数:** +- `indexCount` - 索引数量 +- `instanceCount` - 实例数量(默认1) +- `startIndex` - 起始索引 +- `baseVertex` - 基础顶点索引 +- `startInstance` - 起始实例索引 + +**示例:** + +```cpp +cmdList->DrawIndexed(36); // 绘制36个索引 +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/draw.md b/docs/api/rhi/command-list/draw.md new file mode 100644 index 0000000..70914f1 --- /dev/null +++ b/docs/api/rhi/command-list/draw.md @@ -0,0 +1,23 @@ +# RHICommandList::Draw + +```cpp +virtual void Draw(uint32_t vertexCount, uint32_t instanceCount = 1, uint32_t startVertex = 0, uint32_t startInstance = 0) = 0; +``` + +绘制调用。 + +**参数:** +- `vertexCount` - 顶点数量 +- `instanceCount` - 实例数量(默认1) +- `startVertex` - 起始顶点索引 +- `startInstance` - 起始实例索引 + +**示例:** + +```cpp +cmdList->Draw(36); // 绘制36个顶点 +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/methods.md b/docs/api/rhi/command-list/methods.md new file mode 100644 index 0000000..ed6e704 --- /dev/null +++ b/docs/api/rhi/command-list/methods.md @@ -0,0 +1,201 @@ +# RHICommandList 方法 + +## Reset + +```cpp +virtual void Reset() = 0; +``` + +重置命令列表,开始新的录制。 + +## Close + +```cpp +virtual void Close() = 0; +``` + +关闭命令列表,结束录制。 + +## TransitionBarrier + +```cpp +virtual void TransitionBarrier(void* resource, ResourceStates stateBefore, ResourceStates stateAfter) = 0; +``` + +资源状态转换屏障。 + +## SetPipelineState + +```cpp +virtual void SetPipelineState(void* pso) = 0; +``` + +设置管线状态对象。 + +## SetPrimitiveTopology + +```cpp +virtual void SetPrimitiveTopology(PrimitiveTopology topology) = 0; +``` + +设置图元拓扑。 + +## SetViewport + +```cpp +virtual void SetViewport(const Viewport& viewport) = 0; +``` + +设置视口。 + +## SetViewports + +```cpp +virtual void SetViewports(uint32_t count, const Viewport* viewports) = 0; +``` + +设置多个视口。 + +## SetScissorRect + +```cpp +virtual void SetScissorRect(const Rect& rect) = 0; +``` + +设置裁剪矩形。 + +## SetScissorRects + +```cpp +virtual void SetScissorRects(uint32_t count, const Rect* rects) = 0; +``` + +设置多个裁剪矩形。 + +## SetRenderTargets + +```cpp +virtual void SetRenderTargets(uint32_t count, void** renderTargets, void* depthStencil = nullptr) = 0; +``` + +设置渲染目标。 + +## SetDepthStencilState + +```cpp +virtual void SetDepthStencilState(const DepthStencilState& state) = 0; +``` + +设置深度模板状态。 + +## SetStencilRef + +```cpp +virtual void SetStencilRef(uint8_t ref) = 0; +``` + +设置模板参考值。 + +## SetBlendState + +```cpp +virtual void SetBlendState(const BlendState& state) = 0; +``` + +设置混合状态。 + +## SetBlendFactor + +```cpp +virtual void SetBlendFactor(const float factor[4]) = 0; +``` + +设置混合因子。 + +## SetVertexBuffer + +```cpp +virtual void SetVertexBuffer(uint32_t slot, void* buffer, uint64_t offset, uint32_t stride) = 0; +``` + +设置顶点缓冲。 + +## SetVertexBuffers + +```cpp +virtual void SetVertexBuffers(uint32_t startSlot, uint32_t count, const uint64_t* buffers, const uint64_t* offsets, const uint32_t* strides) = 0; +``` + +设置多个顶点缓冲。 + +## SetIndexBuffer + +```cpp +virtual void SetIndexBuffer(void* buffer, uint64_t offset, Format format) = 0; +``` + +设置索引缓冲。 + +## Draw + +```cpp +virtual void Draw(uint32_t vertexCount, uint32_t instanceCount = 1, uint32_t startVertex = 0, uint32_t startInstance = 0) = 0; +``` + +绘制调用。 + +## DrawIndexed + +```cpp +virtual void DrawIndexed(uint32_t indexCount, uint32_t instanceCount = 1, uint32_t startIndex = 0, int32_t baseVertex = 0, uint32_t startInstance = 0) = 0; +``` + +索引绘制调用。 + +## Clear + +```cpp +virtual void Clear(float r, float g, float b, float a, uint32_t buffers) = 0; +``` + +清除缓冲。 + +## ClearRenderTarget + +```cpp +virtual void ClearRenderTarget(void* renderTarget, const float color[4]) = 0; +``` + +清除渲染目标。 + +## ClearDepthStencil + +```cpp +virtual void ClearDepthStencil(void* depthStencil, float depth, uint8_t stencil) = 0; +``` + +清除深度模板。 + +## CopyResource + +```cpp +virtual void CopyResource(void* dst, void* src) = 0; +``` + +复制资源。 + +## Dispatch + +```cpp +virtual void Dispatch(uint32_t x, uint32_t y, uint32_t z) = 0; +``` + +分发计算着色器。 + +## Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +释放命令列表资源。 diff --git a/docs/api/rhi/command-list/reset.md b/docs/api/rhi/command-list/reset.md new file mode 100644 index 0000000..ed0ea74 --- /dev/null +++ b/docs/api/rhi/command-list/reset.md @@ -0,0 +1,13 @@ +# RHICommandList::Reset + +```cpp +virtual void Reset() = 0; +``` + +重置命令列表以重新录制。 + +**复杂度:** O(1) + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-blend-factor.md b/docs/api/rhi/command-list/set-blend-factor.md new file mode 100644 index 0000000..a075922 --- /dev/null +++ b/docs/api/rhi/command-list/set-blend-factor.md @@ -0,0 +1,21 @@ +# RHICommandList::SetBlendFactor + +```cpp +virtual void SetBlendFactor(const float factor[4]) = 0; +``` + +设置混合因子。 + +**参数:** +- `factor` - 混合因子数组 [r, g, b, a] + +**示例:** + +```cpp +float factor[4] = {0.5f, 0.5f, 0.5f, 1.0f}; +cmdList->SetBlendFactor(factor); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-blend-state.md b/docs/api/rhi/command-list/set-blend-state.md new file mode 100644 index 0000000..2ec1ae3 --- /dev/null +++ b/docs/api/rhi/command-list/set-blend-state.md @@ -0,0 +1,23 @@ +# RHICommandList::SetBlendState + +```cpp +virtual void SetBlendState(const BlendState& state) = 0; +``` + +设置混合状态。 + +**参数:** +- `state` - 混合状态结构体 + +**示例:** + +```cpp +BlendState blendState; +blendState.alphaToCoverageEnable = false; +blendState.independentBlendEnable = false; +cmdList->SetBlendState(blendState); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-depth-stencil-state.md b/docs/api/rhi/command-list/set-depth-stencil-state.md new file mode 100644 index 0000000..1bf38d7 --- /dev/null +++ b/docs/api/rhi/command-list/set-depth-stencil-state.md @@ -0,0 +1,24 @@ +# RHICommandList::SetDepthStencilState + +```cpp +virtual void SetDepthStencilState(const DepthStencilState& state) = 0; +``` + +设置深度模板状态。 + +**参数:** +- `state` - 深度模板状态结构体 + +**示例:** + +```cpp +DepthStencilState dsState; +dsState.depthEnable = true; +dsState.depthWriteMask = true; +dsState.depthFunc = ComparisonFunc::Less; +cmdList->SetDepthStencilState(dsState); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-index-buffer.md b/docs/api/rhi/command-list/set-index-buffer.md new file mode 100644 index 0000000..3698cc9 --- /dev/null +++ b/docs/api/rhi/command-list/set-index-buffer.md @@ -0,0 +1,22 @@ +# RHICommandList::SetIndexBuffer + +```cpp +virtual void SetIndexBuffer(void* buffer, uint64_t offset, Format format) = 0; +``` + +设置索引缓冲区。 + +**参数:** +- `buffer` - 索引缓冲区指针 +- `offset` - 数据偏移量 +- `format` - 索引格式(R16_UINT 或 R32_UINT) + +**示例:** + +```cpp +cmdList->SetIndexBuffer(indexBuffer, 0, Format::R16_UINT); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-pipeline-state.md b/docs/api/rhi/command-list/set-pipeline-state.md new file mode 100644 index 0000000..98ac03e --- /dev/null +++ b/docs/api/rhi/command-list/set-pipeline-state.md @@ -0,0 +1,20 @@ +# RHICommandList::SetPipelineState + +```cpp +virtual void SetPipelineState(void* pso) = 0; +``` + +设置渲染管线状态对象。 + +**参数:** +- `pso` - 管线状态对象指针 + +**示例:** + +```cpp +cmdList->SetPipelineState(pipelineState); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-primitive-topology.md b/docs/api/rhi/command-list/set-primitive-topology.md new file mode 100644 index 0000000..4efd502 --- /dev/null +++ b/docs/api/rhi/command-list/set-primitive-topology.md @@ -0,0 +1,20 @@ +# RHICommandList::SetPrimitiveTopology + +```cpp +virtual void SetPrimitiveTopology(PrimitiveTopology topology) = 0; +``` + +设置图元拓扑类型。 + +**参数:** +- `topology` - 图元拓扑类型(点、线、三角形等) + +**示例:** + +```cpp +cmdList->SetPrimitiveTopology(PrimitiveTopology::TriangleList); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-render-targets.md b/docs/api/rhi/command-list/set-render-targets.md new file mode 100644 index 0000000..3e826cd --- /dev/null +++ b/docs/api/rhi/command-list/set-render-targets.md @@ -0,0 +1,23 @@ +# RHICommandList::SetRenderTargets + +```cpp +virtual void SetRenderTargets(uint32_t count, void** renderTargets, void* depthStencil = nullptr) = 0; +``` + +设置渲染目标和深度模板缓冲区。 + +**参数:** +- `count` - 渲染目标数量 +- `renderTargets` - 渲染目标数组 +- `depthStencil` - 深度模板缓冲区(可选) + +**示例:** + +```cpp +void* targets[1] = {renderTarget}; +cmdList->SetRenderTargets(1, targets, depthStencil); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-scissor-rect.md b/docs/api/rhi/command-list/set-scissor-rect.md new file mode 100644 index 0000000..5cc7a75 --- /dev/null +++ b/docs/api/rhi/command-list/set-scissor-rect.md @@ -0,0 +1,25 @@ +# RHICommandList::SetScissorRect + +```cpp +virtual void SetScissorRect(const Rect& rect) = 0; +``` + +设置裁剪矩形。 + +**参数:** +- `rect` - 裁剪矩形结构体 + +**示例:** + +```cpp +Rect rect; +rect.left = 0; +rect.top = 0; +rect.right = 640; +rect.bottom = 480; +cmdList->SetScissorRect(rect); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-scissor-rects.md b/docs/api/rhi/command-list/set-scissor-rects.md new file mode 100644 index 0000000..fa857b9 --- /dev/null +++ b/docs/api/rhi/command-list/set-scissor-rects.md @@ -0,0 +1,24 @@ +# RHICommandList::SetScissorRects + +```cpp +virtual void SetScissorRects(uint32_t count, const Rect* rects) = 0; +``` + +设置多个裁剪矩形。 + +**参数:** +- `count` - 裁剪矩形数量 +- `rects` - 裁剪矩形数组指针 + +**示例:** + +```cpp +Rect rects[2]; +rects[0] = {0, 0, 640, 480}; +rects[1] = {640, 0, 640, 480}; +cmdList->SetScissorRects(2, rects); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-stencil-ref.md b/docs/api/rhi/command-list/set-stencil-ref.md new file mode 100644 index 0000000..eb1f4d0 --- /dev/null +++ b/docs/api/rhi/command-list/set-stencil-ref.md @@ -0,0 +1,20 @@ +# RHICommandList::SetStencilRef + +```cpp +virtual void SetStencilRef(uint8_t ref) = 0; +``` + +设置模板参考值。 + +**参数:** +- `ref` - 模板参考值 + +**示例:** + +```cpp +cmdList->SetStencilRef(0xFF); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-vertex-buffer.md b/docs/api/rhi/command-list/set-vertex-buffer.md new file mode 100644 index 0000000..0b13f64 --- /dev/null +++ b/docs/api/rhi/command-list/set-vertex-buffer.md @@ -0,0 +1,23 @@ +# RHICommandList::SetVertexBuffer + +```cpp +virtual void SetVertexBuffer(uint32_t slot, void* buffer, uint64_t offset, uint32_t stride) = 0; +``` + +设置顶点缓冲区。 + +**参数:** +- `slot` - 顶点缓冲区槽位 +- `buffer` - 顶点缓冲区指针 +- `offset` - 数据偏移量 +- `stride` - 顶点步长 + +**示例:** + +```cpp +cmdList->SetVertexBuffer(0, vertexBuffer, 0, sizeof(Vertex)); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-vertex-buffers.md b/docs/api/rhi/command-list/set-vertex-buffers.md new file mode 100644 index 0000000..23bfd83 --- /dev/null +++ b/docs/api/rhi/command-list/set-vertex-buffers.md @@ -0,0 +1,27 @@ +# RHICommandList::SetVertexBuffers + +```cpp +virtual void SetVertexBuffers(uint32_t startSlot, uint32_t count, const uint64_t* buffers, const uint64_t* offsets, const uint32_t* strides) = 0; +``` + +设置多个顶点缓冲区。 + +**参数:** +- `startSlot` - 起始槽位 +- `count` - 缓冲区数量 +- `buffers` - 缓冲区指针数组 +- `offsets` - 偏移量数组 +- `strides` - 步长数组 + +**示例:** + +```cpp +uint64_t buffers[2] = {(uint64_t)vb1, (uint64_t)vb2}; +uint64_t offsets[2] = {0, 0}; +uint32_t strides[2] = {sizeof(Vertex), sizeof(Vertex)}; +cmdList->SetVertexBuffers(0, 2, buffers, offsets, strides); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-viewport.md b/docs/api/rhi/command-list/set-viewport.md new file mode 100644 index 0000000..53cff93 --- /dev/null +++ b/docs/api/rhi/command-list/set-viewport.md @@ -0,0 +1,27 @@ +# RHICommandList::SetViewport + +```cpp +virtual void SetViewport(const Viewport& viewport) = 0; +``` + +设置视口。 + +**参数:** +- `viewport` - 视口结构体 + +**示例:** + +```cpp +Viewport vp; +vp.topLeftX = 0; +vp.topLeftY = 0; +vp.width = 1280; +vp.height = 720; +vp.minDepth = 0.0f; +vp.maxDepth = 1.0f; +cmdList->SetViewport(vp); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/set-viewports.md b/docs/api/rhi/command-list/set-viewports.md new file mode 100644 index 0000000..13640fb --- /dev/null +++ b/docs/api/rhi/command-list/set-viewports.md @@ -0,0 +1,24 @@ +# RHICommandList::SetViewports + +```cpp +virtual void SetViewports(uint32_t count, const Viewport* viewports) = 0; +``` + +设置多个视口。 + +**参数:** +- `count` - 视口数量 +- `viewports` - 视口数组指针 + +**示例:** + +```cpp +Viewport viewports[2]; +viewports[0] = {0, 0, 640, 720, 0.0f, 1.0f}; +viewports[1] = {640, 0, 640, 720, 0.0f, 1.0f}; +cmdList->SetViewports(2, viewports); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/shutdown.md b/docs/api/rhi/command-list/shutdown.md new file mode 100644 index 0000000..477a6fc --- /dev/null +++ b/docs/api/rhi/command-list/shutdown.md @@ -0,0 +1,13 @@ +# RHICommandList::Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +关闭命令列表,释放所有相关资源。 + +**复杂度:** O(n) - 取决于管理的命令数量 + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-list/transition-barrier.md b/docs/api/rhi/command-list/transition-barrier.md new file mode 100644 index 0000000..2c0a7ef --- /dev/null +++ b/docs/api/rhi/command-list/transition-barrier.md @@ -0,0 +1,23 @@ +# RHICommandList::TransitionBarrier + +```cpp +virtual void TransitionBarrier(void* resource, ResourceStates stateBefore, ResourceStates stateAfter) = 0; +``` + +设置资源状态转换屏障,确保 GPU 资源在状态转换前完成所有操作。 + +**参数:** +- `resource` - 目标资源指针 +- `stateBefore` - 转换前的资源状态 +- `stateAfter` - 转换后的资源状态 + +**示例:** + +```cpp +// 将纹理从渲染目标状态转换到着色器读取状态 +cmdList->TransitionBarrier(texture, ResourceStates::RenderTarget, ResourceStates::ShaderResource); +``` + +## 相关文档 + +- [RHICommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/command-queue/command-queue.md b/docs/api/rhi/command-queue/command-queue.md new file mode 100644 index 0000000..bb29210 --- /dev/null +++ b/docs/api/rhi/command-queue/command-queue.md @@ -0,0 +1,50 @@ +# RHICommandQueue + +**命名空间**: `XCEngine::RHI` + +**类型**: `class` (abstract) + +**描述**: GPU 命令队列抽象接口,负责提交和执行命令列表,以及 GPU/CPU 同步。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Shutdown`](shutdown.md) | 关闭并释放资源 | +| [`ExecuteCommandLists`](execute-command-lists.md) | 执行命令列表 | +| [`Signal`](signal.md) | 信号栅栏 | +| [`Wait`](../../threading/task-group/wait.md) | 等待栅栏 | +| [`GetCompletedValue`](get-completed-value.md) | 获取完成值 | +| [`WaitForIdle`](wait-for-idle.md) | 等待空闲 | +| [`GetType`](get-type.md) | 获取队列类型 | +| [`GetTimestampFrequency`](get-timestamp-frequency.md) | 获取时间戳频率 | +| [`GetNativeHandle`](get-native-handle.md) | 获取原生句柄 | + +## 命令队列类型 (CommandQueueType) + +| 枚举值 | 描述 | +|--------|------| +| `Direct` | 直接队列,用于图形和计算命令 | +| `Compute` | 计算队列,专门用于计算着色器 | +| `Copy` | 复制队列,专门用于资源复制 | + +## 使用示例 + +```cpp +CommandQueueDesc queueDesc; +queueDesc.queueType = (uint32_t)CommandQueueType::Direct; +RHICommandQueue* commandQueue = device->CreateCommandQueue(queueDesc); + +FenceDesc fenceDesc; +RHIFence* fence = device->CreateFence(fenceDesc); + +commandQueue->ExecuteCommandLists(1, (void**)&commandList); +commandQueue->Signal(fence, 1); +fence->Wait(1); +``` + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHICommandList](../command-list/command-list.md) - 命令列表 +- [RHIFence](../fence/fence.md) - 同步栅栏 diff --git a/docs/api/rhi/command-queue/execute-command-lists.md b/docs/api/rhi/command-queue/execute-command-lists.md new file mode 100644 index 0000000..631b5a2 --- /dev/null +++ b/docs/api/rhi/command-queue/execute-command-lists.md @@ -0,0 +1,22 @@ +# RHICommandQueue::ExecuteCommandLists + +```cpp +virtual void ExecuteCommandLists(uint32_t count, void** lists) = 0; +``` + +执行命令列表。 + +**参数:** +- `count` - 命令列表数量 +- `lists` - 命令列表指针数组 + +**示例:** + +```cpp +void* lists[1] = {cmdList}; +cmdQueue->ExecuteCommandLists(1, lists); +``` + +## 相关文档 + +- [RHICommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/command-queue/get-completed-value.md b/docs/api/rhi/command-queue/get-completed-value.md new file mode 100644 index 0000000..bdf98aa --- /dev/null +++ b/docs/api/rhi/command-queue/get-completed-value.md @@ -0,0 +1,19 @@ +# RHICommandQueue::GetCompletedValue + +```cpp +virtual uint64_t GetCompletedValue() = 0; +``` + +获取栅栏已完成值。 + +**返回:** 已完成的信号值 + +**示例:** + +```cpp +uint64_t value = cmdQueue->GetCompletedValue(); +``` + +## 相关文档 + +- [RHICommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/command-queue/get-native-handle.md b/docs/api/rhi/command-queue/get-native-handle.md new file mode 100644 index 0000000..35e15a5 --- /dev/null +++ b/docs/api/rhi/command-queue/get-native-handle.md @@ -0,0 +1,15 @@ +# RHICommandQueue::GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 + +**返回:** 原生命令队列句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [RHICommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/command-queue/get-timestamp-frequency.md b/docs/api/rhi/command-queue/get-timestamp-frequency.md new file mode 100644 index 0000000..4622fbc --- /dev/null +++ b/docs/api/rhi/command-queue/get-timestamp-frequency.md @@ -0,0 +1,19 @@ +# RHICommandQueue::GetTimestampFrequency + +```cpp +virtual uint64_t GetTimestampFrequency() const = 0; +``` + +获取时间戳频率。 + +**返回:** 时间戳频率(每秒计数) + +**示例:** + +```cpp +uint64_t freq = cmdQueue->GetTimestampFrequency(); +``` + +## 相关文档 + +- [RHICommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/command-queue/get-type.md b/docs/api/rhi/command-queue/get-type.md new file mode 100644 index 0000000..76e5a5d --- /dev/null +++ b/docs/api/rhi/command-queue/get-type.md @@ -0,0 +1,15 @@ +# RHICommandQueue::GetType + +```cpp +virtual CommandQueueType GetType() const = 0; +``` + +获取命令队列类型。 + +**返回:** 命令队列类型枚举值 + +**复杂度:** O(1) + +## 相关文档 + +- [RHICommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/command-queue/methods.md b/docs/api/rhi/command-queue/methods.md new file mode 100644 index 0000000..b44ea12 --- /dev/null +++ b/docs/api/rhi/command-queue/methods.md @@ -0,0 +1,73 @@ +# RHICommandQueue 方法 + +## Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +关闭命令队列。 + +## ExecuteCommandLists + +```cpp +virtual void ExecuteCommandLists(uint32_t count, void** lists) = 0; +``` + +执行命令列表。 + +## Signal + +```cpp +virtual void Signal(RHIFence* fence, uint64_t value) = 0; +``` + +信号通知栅栏。 + +## Wait + +```cpp +virtual void Wait(RHIFence* fence, uint64_t value) = 0; +``` + +等待栅栏。 + +## GetCompletedValue + +```cpp +virtual uint64_t GetCompletedValue() = 0; +``` + +获取已完成的值。 + +## WaitForIdle + +```cpp +virtual void WaitForIdle() = 0; +``` + +等待队列空闲。 + +## GetType + +```cpp +virtual CommandQueueType GetType() const = 0; +``` + +获取队列类型。 + +## GetTimestampFrequency + +```cpp +virtual uint64_t GetTimestampFrequency() const = 0; +``` + +获取时间戳频率。 + +## GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 diff --git a/docs/api/rhi/command-queue/shutdown.md b/docs/api/rhi/command-queue/shutdown.md new file mode 100644 index 0000000..580b1de --- /dev/null +++ b/docs/api/rhi/command-queue/shutdown.md @@ -0,0 +1,13 @@ +# RHICommandQueue::Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +关闭命令队列,释放所有相关资源。 + +**复杂度:** O(n) - 取决于管理的命令列表数量 + +## 相关文档 + +- [RHICommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/command-queue/signal.md b/docs/api/rhi/command-queue/signal.md new file mode 100644 index 0000000..c9bcd53 --- /dev/null +++ b/docs/api/rhi/command-queue/signal.md @@ -0,0 +1,21 @@ +# RHICommandQueue::Signal + +```cpp +virtual void Signal(RHIFence* fence, uint64_t value) = 0; +``` + +向栅栏发送信号。 + +**参数:** +- `fence` - 目标栅栏 +- `value` - 信号值 + +**示例:** + +```cpp +cmdQueue->Signal(fence, 1); +``` + +## 相关文档 + +- [RHICommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/command-queue/wait-for-idle.md b/docs/api/rhi/command-queue/wait-for-idle.md new file mode 100644 index 0000000..80a50fc --- /dev/null +++ b/docs/api/rhi/command-queue/wait-for-idle.md @@ -0,0 +1,17 @@ +# RHICommandQueue::WaitForIdle + +```cpp +virtual void WaitForIdle() = 0; +``` + +等待命令队列完成所有操作。 + +**示例:** + +```cpp +cmdQueue->WaitForIdle(); +``` + +## 相关文档 + +- [RHICommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/buffer/buffer.md b/docs/api/rhi/d3d12/buffer/buffer.md new file mode 100644 index 0000000..90f3506 --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/buffer.md @@ -0,0 +1,37 @@ +# D3D12Buffer + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 缓冲区的 D3D12 实现,继承自 `RHIBuffer`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](initialize.md) | 初始化缓冲区 | +| [`InitializeFromExisting`](initialize-from-existing.md) | 从现有资源初始化 | +| [`InitializeWithData`](initialize-with-data.md) | 初始化并写入数据 | +| [`Shutdown`](shutdown.md) | 关闭缓冲区 | +| [`UpdateData`](update-data.md) | 更新数据 | +| [`Map`](map.md) | 映射缓冲区 | +| [`Unmap`](unmap.md) | 取消映射 | +| [`SetData`](set-data.md) | 设置数据 | +| [`GetResource`](get-resource.md) | 获取 D3D12 资源 | +| [`GetDesc`](get-desc.md) | 获取描述符 | +| [`GetGPUVirtualAddress`](get-gpu-virtual-address.md) | 获取 GPU 虚拟地址 | +| [`GetGPUAddress`](get-gpu-address.md) | 获取 GPU 地址 | +| [`GetSize`](get-size.md) | 获取缓冲区大小 | +| [`GetState`](get-state.md) | 获取资源状态 | +| [`SetState`](../../buffer/set-state.md) | 设置资源状态 | +| [`GetName`](get-name.md) | 获取资源名称 | +| [`SetName`](../../buffer/set-name.md) | 设置资源名称 | +| [`GetStride`](get-stride.md) | 获取步长 | +| [`SetStride`](../../buffer/set-stride.md) | 设置步长 | +| [`GetBufferType`](get-buffer-type.md) | 获取缓冲区类型 | +| [`SetBufferType`](../../buffer/set-buffer-type.md) | 设置缓冲区类型 | +| [`GetNativeHandle`](get-native-handle.md) | 获取原生句柄 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) +- [RHIBuffer](../../buffer/buffer.md) - 抽象缓冲区接口 diff --git a/docs/api/rhi/d3d12/buffer/get-buffer-type.md b/docs/api/rhi/d3d12/buffer/get-buffer-type.md new file mode 100644 index 0000000..44698e0 --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/get-buffer-type.md @@ -0,0 +1,16 @@ +# D3D12Buffer::GetBufferType / SetBufferType + +## 函数签名 + +```cpp +BufferType GetBufferType() const override +void SetBufferType(BufferType type) override +``` + +## 中文描述 + +获取和设置缓冲区类型(Vertex / Index / Constant 等)。 + +## 复杂度 + +O(1) diff --git a/docs/api/rhi/d3d12/buffer/get-desc.md b/docs/api/rhi/d3d12/buffer/get-desc.md new file mode 100644 index 0000000..49bfeab --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/get-desc.md @@ -0,0 +1,19 @@ +# D3D12Buffer::GetDesc + +## 函数签名 + +```cpp +D3D12_RESOURCE_DESC GetDesc() const +``` + +## 中文描述 + +获取 D3D12 资源描述结构。 + +## 返回值 + +`D3D12_RESOURCE_DESC` - 资源描述 + +## 复杂度 + +O(1) diff --git a/docs/api/rhi/d3d12/buffer/get-gpu-address.md b/docs/api/rhi/d3d12/buffer/get-gpu-address.md new file mode 100644 index 0000000..e8c6468 --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/get-gpu-address.md @@ -0,0 +1,19 @@ +# D3D12Buffer::GetGPUAddress + +## 函数签名 + +```cpp +uint64_t GetGPUAddress() const +``` + +## 中文描述 + +获取 GPU 地址(等同于 `GetGPUVirtualAddress`)。 + +## 返回值 + +`uint64_t` - GPU 地址 + +## 复杂度 + +O(1) diff --git a/docs/api/rhi/d3d12/buffer/get-gpu-virtual-address.md b/docs/api/rhi/d3d12/buffer/get-gpu-virtual-address.md new file mode 100644 index 0000000..746d44b --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/get-gpu-virtual-address.md @@ -0,0 +1,19 @@ +# D3D12Buffer::GetGPUVirtualAddress + +## 函数签名 + +```cpp +D3D12_GPU_VIRTUAL_ADDRESS GetGPUVirtualAddress() const +``` + +## 中文描述 + +获取 GPU 虚拟地址,用于根签名绑定。 + +## 返回值 + +`D3D12_GPU_VIRTUAL_ADDRESS` - GPU 虚拟地址 + +## 复杂度 + +O(1) diff --git a/docs/api/rhi/d3d12/buffer/get-name.md b/docs/api/rhi/d3d12/buffer/get-name.md new file mode 100644 index 0000000..4d3d873 --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/get-name.md @@ -0,0 +1,16 @@ +# D3D12Buffer::GetName / SetName + +## 函数签名 + +```cpp +const std::string& GetName() const override +void SetName(const std::string& name) override +``` + +## 中文描述 + +获取和设置对象名称(用于调试)。 + +## 复杂度 + +O(1) diff --git a/docs/api/rhi/d3d12/buffer/get-native-handle.md b/docs/api/rhi/d3d12/buffer/get-native-handle.md new file mode 100644 index 0000000..bf64fcd --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/get-native-handle.md @@ -0,0 +1,19 @@ +# D3D12Buffer::GetNativeHandle + +## 函数签名 + +```cpp +void* GetNativeHandle() override +``` + +## 中文描述 + +返回原生句柄,即 `ID3D12Resource*`。 + +## 返回值 + +`void*` - 原生句柄 + +## 复杂度 + +O(1) diff --git a/docs/api/rhi/d3d12/buffer/get-resource.md b/docs/api/rhi/d3d12/buffer/get-resource.md new file mode 100644 index 0000000..b757030 --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/get-resource.md @@ -0,0 +1,19 @@ +# D3D12Buffer::GetResource + +## 函数签名 + +```cpp +ID3D12Resource* GetResource() const +``` + +## 中文描述 + +获取底层 `ID3D12Resource` 指针。 + +## 返回值 + +`ID3D12Resource*` - D3D12 资源指针 + +## 复杂度 + +O(1) diff --git a/docs/api/rhi/d3d12/buffer/get-size.md b/docs/api/rhi/d3d12/buffer/get-size.md new file mode 100644 index 0000000..9a1e8bc --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/get-size.md @@ -0,0 +1,19 @@ +# D3D12Buffer::GetSize + +## 函数签名 + +```cpp +uint64_t GetSize() const override +``` + +## 中文描述 + +获取缓冲区大小(字节)。 + +## 返回值 + +`uint64_t` - 缓冲区大小 + +## 复杂度 + +O(1) diff --git a/docs/api/rhi/d3d12/buffer/get-state.md b/docs/api/rhi/d3d12/buffer/get-state.md new file mode 100644 index 0000000..f1b2e93 --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/get-state.md @@ -0,0 +1,16 @@ +# D3D12Buffer::GetState / SetState + +## 函数签名 + +```cpp +ResourceStates GetState() const +void SetState(ResourceStates state) +``` + +## 中文描述 + +获取和设置当前资源状态。用于状态跟踪和屏障生成。 + +## 复杂度 + +O(1) diff --git a/docs/api/rhi/d3d12/buffer/get-stride.md b/docs/api/rhi/d3d12/buffer/get-stride.md new file mode 100644 index 0000000..b29afae --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/get-stride.md @@ -0,0 +1,16 @@ +# D3D12Buffer::GetStride / SetStride + +## 函数签名 + +```cpp +uint32_t GetStride() const override +void SetStride(uint32_t stride) override +``` + +## 中文描述 + +获取和设置顶点缓冲区步长(字节)。 + +## 复杂度 + +O(1) diff --git a/docs/api/rhi/d3d12/buffer/initialize-from-existing.md b/docs/api/rhi/d3d12/buffer/initialize-from-existing.md new file mode 100644 index 0000000..d8eb37c --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/initialize-from-existing.md @@ -0,0 +1,35 @@ +# D3D12Buffer::InitializeFromExisting + +## 函数签名 + +```cpp +bool InitializeFromExisting(ID3D12Resource* resource) +``` + +## 中文描述 + +从已存在的 D3D12 资源对象初始化缓冲区包装类,不分配新资源。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `resource` | `ID3D12Resource*` | 已存在的 D3D12 资源指针 | + +## 返回值 + +`bool` - 初始化是否成功 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +ComPtr existingResource; +device->CreateReservedResource(&desc, state, nullptr, IID_PPV_ARGS(&existingResource)); + +D3D12Buffer buffer; +buffer.InitializeFromExisting(existingResource.Get()); +``` diff --git a/docs/api/rhi/d3d12/buffer/initialize-with-data.md b/docs/api/rhi/d3d12/buffer/initialize-with-data.md new file mode 100644 index 0000000..41047bc --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/initialize-with-data.md @@ -0,0 +1,42 @@ +# D3D12Buffer::InitializeWithData + +## 函数签名 + +```cpp +bool InitializeWithData(ID3D12Device* device, ID3D12GraphicsCommandList* commandList, const void* data, uint64_t size, D3D12_RESOURCE_STATES finalState) +``` + +## 中文描述 + +创建缓冲区并通过命令列表从内存数据初始化内容。内部会自动创建上传堆、复制数据、转换状态。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `device` | `ID3D12Device*` | D3D12 设备指针 | +| `commandList` | `ID3D12GraphicsCommandList*` | 命令列表(用于复制操作) | +| `data` | `const void*` | 初始数据指针 | +| `size` | `uint64_t` | 数据大小(字节) | +| `finalState` | `D3D12_RESOURCE_STATES` | 数据复制完成后的目标状态 | + +## 返回值 + +`bool` - 初始化是否成功 + +## 复杂度 + +O(n) - 取决于数据大小,内部创建临时上传堆 + +## 示例 + +```cpp +uint16_t indices[] = { 0, 1, 2, 1, 3, 2 }; +D3D12Buffer indexBuffer; +D3D12Buffer::InitializeWithData( + device->GetDevice(), + cmdList->GetCommandList(), + indices, + sizeof(indices), + D3D12_RESOURCE_STATE_INDEX_BUFFER); +``` diff --git a/docs/api/rhi/d3d12/buffer/initialize.md b/docs/api/rhi/d3d12/buffer/initialize.md new file mode 100644 index 0000000..94ef413 --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/initialize.md @@ -0,0 +1,39 @@ +# D3D12Buffer::Initialize + +## 函数签名 + +```cpp +bool Initialize(ID3D12Device* device, uint64_t size, D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON, D3D12_HEAP_TYPE heapType = D3D12_HEAP_TYPE_DEFAULT) +``` + +## 中文描述 + +创建新缓冲区,分配 D3D12 显存资源。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `device` | `ID3D12Device*` | D3D12 设备指针 | +| `size` | `uint64_t` | 缓冲区大小(字节) | +| `initialState` | `D3D12_RESOURCE_STATES` | 初始资源状态(默认 COMMON) | +| `heapType` | `D3D12_HEAP_TYPE` | 堆类型:DEFAULT(默认)、UPLOAD(上传)、READBACK(回读) | + +## 返回值 + +`bool` - 初始化是否成功 + +## 复杂度 + +O(n) - 取决于缓冲区大小 + +## 示例 + +```cpp +D3D12Buffer vertexBuffer; +vertexBuffer.Initialize( + device->GetDevice(), + sizeof(Vertex) * vertexCount, + D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, + D3D12_HEAP_TYPE_DEFAULT); +``` diff --git a/docs/api/rhi/d3d12/buffer/map.md b/docs/api/rhi/d3d12/buffer/map.md new file mode 100644 index 0000000..fbe0291 --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/map.md @@ -0,0 +1,27 @@ +# D3D12Buffer::Map + +## 函数签名 + +```cpp +void* Map() override +``` + +## 中文描述 + +将缓冲区内存映射到 CPU 可访问地址。仅对 UPLOAD 或 READBACK 堆有效。 + +## 返回值 + +`void*` - 映射的内存指针 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +void* mapped = uploadBuffer.Map(); +memcpy(mapped, vertexData, sizeof(vertexData)); +buffer.Unmap(); +``` diff --git a/docs/api/rhi/d3d12/buffer/set-data.md b/docs/api/rhi/d3d12/buffer/set-data.md new file mode 100644 index 0000000..e3f6376 --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/set-data.md @@ -0,0 +1,23 @@ +# D3D12Buffer::SetData + +## 函数签名 + +```cpp +void SetData(const void* data, size_t size, size_t offset = 0) override +``` + +## 中文描述 + +设置缓冲区数据。通过 Map/Unmap 实现。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `data` | `const void*` | 数据指针 | +| `size` | `size_t` | 数据大小 | +| `offset` | `size_t` | 缓冲区内的偏移量 | + +## 复杂度 + +O(n) diff --git a/docs/api/rhi/d3d12/buffer/shutdown.md b/docs/api/rhi/d3d12/buffer/shutdown.md new file mode 100644 index 0000000..9c3c479 --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/shutdown.md @@ -0,0 +1,15 @@ +# D3D12Buffer::Shutdown + +## 函数签名 + +```cpp +void Shutdown() override +``` + +## 中文描述 + +释放 D3D12 缓冲区资源,将成员变量置为空。 + +## 复杂度 + +O(1) diff --git a/docs/api/rhi/d3d12/buffer/unmap.md b/docs/api/rhi/d3d12/buffer/unmap.md new file mode 100644 index 0000000..2ee8db6 --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/unmap.md @@ -0,0 +1,15 @@ +# D3D12Buffer::Unmap + +## 函数签名 + +```cpp +void Unmap() override +``` + +## 中文描述 + +解除缓冲区内存映射。 + +## 复杂度 + +O(1) diff --git a/docs/api/rhi/d3d12/buffer/update-data.md b/docs/api/rhi/d3d12/buffer/update-data.md new file mode 100644 index 0000000..ab757c1 --- /dev/null +++ b/docs/api/rhi/d3d12/buffer/update-data.md @@ -0,0 +1,28 @@ +# D3D12Buffer::UpdateData + +## 函数签名 + +```cpp +void UpdateData(const void* data, uint64_t size) +``` + +## 中文描述 + +更新缓冲区数据。要求缓冲区使用 UPLOAD 堆类型,否则行为未定义。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `data` | `const void*` | 新数据指针 | +| `size` | `uint64_t` | 数据大小 | + +## 复杂度 + +O(n) + +## 示例 + +```cpp +uploadBuffer.UpdateData(newData, dataSize); +``` diff --git a/docs/api/rhi/d3d12/command-allocator/command-allocator.md b/docs/api/rhi/d3d12/command-allocator/command-allocator.md new file mode 100644 index 0000000..7a7dfa9 --- /dev/null +++ b/docs/api/rhi/d3d12/command-allocator/command-allocator.md @@ -0,0 +1,19 @@ +# D3D12CommandAllocator + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 命令分配器的 D3D12 实现。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化命令分配器 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭命令分配器 | +| [`Reset`](../../command-list/reset.md) | 重置命令分配器 | +| [`IsReady`](is-ready.md) | 检查是否就绪 | +| [`GetCommandAllocator`](get-command-allocator.md) | 获取 D3D12 命令分配器 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) diff --git a/docs/api/rhi/d3d12/command-allocator/get-command-allocator.md b/docs/api/rhi/d3d12/command-allocator/get-command-allocator.md new file mode 100644 index 0000000..da32a50 --- /dev/null +++ b/docs/api/rhi/d3d12/command-allocator/get-command-allocator.md @@ -0,0 +1,15 @@ +# D3D12CommandAllocator::GetCommandAllocator + +```cpp +ID3D12CommandAllocator* GetCommandAllocator() const { return m_commandAllocator.Get(); } +``` + +获取底层的 D3D12 命令分配器接口。 + +**返回:** `ID3D12CommandAllocator*` + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandAllocator 总览](command-allocator.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-allocator/is-ready.md b/docs/api/rhi/d3d12/command-allocator/is-ready.md new file mode 100644 index 0000000..c70acb1 --- /dev/null +++ b/docs/api/rhi/d3d12/command-allocator/is-ready.md @@ -0,0 +1,15 @@ +# D3D12CommandAllocator::IsReady + +```cpp +bool IsReady() const; +``` + +检查命令分配器是否准备就绪。 + +**返回:** 分配器是否准备就绪 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandAllocator 总览](command-allocator.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/alias-barrier.md b/docs/api/rhi/d3d12/command-list/alias-barrier.md new file mode 100644 index 0000000..c336fcc --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/alias-barrier.md @@ -0,0 +1,17 @@ +# D3D12CommandList::AliasBarrier + +```cpp +void AliasBarrier(void* beforeResource = nullptr, void* afterResource = nullptr); +``` + +添加资源别名屏障。 + +**参数:** +- `beforeResource` - 别名切换前的资源 +- `afterResource` - 别名切换后的资源 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/begin-query.md b/docs/api/rhi/d3d12/command-list/begin-query.md new file mode 100644 index 0000000..8fb4f0b --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/begin-query.md @@ -0,0 +1,18 @@ +# D3D12CommandList::BeginQuery + +```cpp +void BeginQuery(ID3D12QueryHeap* queryHeap, QueryType type, uint32_t index); +``` + +开始查询。 + +**参数:** +- `queryHeap` - 查询堆 +- `type` - 查询类型 +- `index` - 查询索引 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/clear-depth-stencil.md b/docs/api/rhi/d3d12/command-list/clear-depth-stencil.md new file mode 100644 index 0000000..961cca0 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/clear-depth-stencil.md @@ -0,0 +1,18 @@ +# D3D12CommandList::ClearDepthStencil + +```cpp +void ClearDepthStencil(void* depthStencil, float depth, uint8_t stencil) override; +``` + +清除深度模板。 + +**参数:** +- `depthStencil` - 深度模板指针 +- `depth` - 深度值 +- `stencil` - 模板值 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/clear-render-target.md b/docs/api/rhi/d3d12/command-list/clear-render-target.md new file mode 100644 index 0000000..e519370 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/clear-render-target.md @@ -0,0 +1,17 @@ +# D3D12CommandList::ClearRenderTarget + +```cpp +void ClearRenderTarget(void* renderTarget, const float color[4]) override; +``` + +清除渲染目标。 + +**参数:** +- `renderTarget` - 渲染目标指针 +- `color` - 清除颜色 [r, g, b, a] + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/command-list.md b/docs/api/rhi/d3d12/command-list/command-list.md new file mode 100644 index 0000000..714fd92 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/command-list.md @@ -0,0 +1,65 @@ +# D3D12CommandList + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 命令列表的 D3D12 实现,继承自 `RHICommandList`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭命令列表 | +| [`Reset`](../../command-list/reset.md) | 重置命令列表 | +| [`Close`](../../command-list/close.md) | 关闭命令列表 | +| [`GetCommandList`](get-command-list.md) | 获取 D3D12 命令列表 | +| [`TransitionBarrier`](transition-barrier.md) | 资源状态转换 | +| [`TransitionBarrierInternal`](transition-barrier-internal.md) | 内部资源状态转换 | +| [`UAVBarrier`](uav-barrier.md) | UAV 屏障 | +| [`AliasBarrier`](alias-barrier.md) | 别名屏障 | +| [`SetPipelineState`](set-pipeline-state.md) | 设置管线状态 | +| [`SetRootSignature`](set-root-signature.md) | 设置根签名 | +| [`SetPrimitiveTopology`](set-primitive-topology.md) | 设置图元拓扑 | +| [`SetViewport`](set-viewport.md) | 设置视口 | +| [`SetViewports`](set-viewports.md) | 设置多个视口 | +| [`SetScissorRect`](set-scissor-rect.md) | 设置裁剪矩形 | +| [`SetScissorRects`](set-scissor-rects.md) | 设置多个裁剪矩形 | +| [`SetRenderTargets`](set-render-targets.md) | 设置渲染目标 | +| [`SetRenderTargetsInternal`](set-render-targets-internal.md) | 内部渲染目标设置 | +| [`SetRenderTargetsHandle`](set-render-targets-handle.md) | 句柄渲染目标设置 | +| [`SetVertexBuffer`](set-vertex-buffer.md) | 设置顶点缓冲 | +| [`SetVertexBuffers`](set-vertex-buffers.md) | 设置多个顶点缓冲 | +| [`SetIndexBuffer`](set-index-buffer.md) | 设置索引缓冲 | +| [`SetDescriptorHeap`](set-descriptor-heap.md) | 设置描述符堆 | +| [`SetDescriptorHeaps`](set-descriptor-heaps.md) | 设置多个描述符堆 | +| [`SetGraphicsDescriptorTable`](set-graphics-descriptor-table.md) | 设置图形描述符表 | +| [`SetComputeDescriptorTable`](set-compute-descriptor-table.md) | 设置计算描述符表 | +| [`SetGraphicsRootConstantBufferView`](set-graphics-root-constant-buffer-view.md) | 设置图形根常量缓冲视图 | +| [`SetGraphicsRoot32BitConstants`](set-graphics-root-32bit-constants.md) | 设置图形根 32 位常量 | +| [`SetGraphicsRootDescriptorTable`](set-graphics-root-descriptor-table.md) | 设置图形根描述符表 | +| [`SetGraphicsRootShaderResourceView`](set-graphics-root-shader-resource-view.md) | 设置图形根着色器资源视图 | +| [`SetStencilRef`](set-stencil-ref.md) | 设置模板引用值 | +| [`SetBlendFactor`](set-blend-factor.md) | 设置混合因子 | +| [`SetDepthBias`](set-depth-bias.md) | 设置深度偏移 | +| [`Draw`](draw.md) | 绘制 | +| [`DrawIndexed`](draw-indexed.md) | 索引绘制 | +| [`DrawInstancedIndirect`](draw-instanced-indirect.md) | 实例化间接绘制 | +| [`DrawIndexedInstancedIndirect`](draw-indexed-instanced-indirect.md) | 索引实例化间接绘制 | +| [`Clear`](../../command-list/clear.md) | 清除 | +| [`ClearRenderTarget`](clear-render-target.md) | 清除渲染目标 | +| [`ClearDepthStencil`](clear-depth-stencil.md) | 清除深度模板 | +| [`CopyResource`](copy-resource.md) | 复制资源 | +| [`CopyBuffer`](copy-buffer.md) | 复制缓冲区 | +| [`CopyTexture`](copy-texture.md) | 复制纹理 | +| [`BeginQuery`](begin-query.md) | 开始查询 | +| [`EndQuery`](end-query.md) | 结束查询 | +| [`ResolveQueryData`](resolve-query-data.md) | 解析查询数据 | +| [`Dispatch`](dispatch.md) | 分发计算任务 | +| [`DispatchIndirect`](dispatch-indirect.md) | 间接分发计算任务 | +| [`ExecuteBundle`](execute-bundle.md) | 执行 Bundle | +| [`GetResourceState`](get-resource-state.md) | 获取资源状态 | +| [`TrackResource`](track-resource.md) | 跟踪资源 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) +- [RHICommandList](../../command-list/command-list.md) - 抽象命令列表接口 diff --git a/docs/api/rhi/d3d12/command-list/copy-buffer.md b/docs/api/rhi/d3d12/command-list/copy-buffer.md new file mode 100644 index 0000000..49fddf4 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/copy-buffer.md @@ -0,0 +1,20 @@ +# D3D12CommandList::CopyBuffer + +```cpp +void CopyBuffer(ID3D12Resource* dst, uint64_t dstOffset, ID3D12Resource* src, uint64_t srcOffset, uint64_t size); +``` + +复制缓冲区。 + +**参数:** +- `dst` - 目标缓冲区 +- `dstOffset` - 目标偏移 +- `src` - 源缓冲区 +- `srcOffset` - 源偏移 +- `size` - 复制大小 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/copy-resource.md b/docs/api/rhi/d3d12/command-list/copy-resource.md new file mode 100644 index 0000000..1ebadd9 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/copy-resource.md @@ -0,0 +1,17 @@ +# D3D12CommandList::CopyResource + +```cpp +void CopyResource(void* dst, void* src) override; +``` + +复制资源。 + +**参数:** +- `dst` - 目标资源指针 +- `src` - 源资源指针 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/copy-texture.md b/docs/api/rhi/d3d12/command-list/copy-texture.md new file mode 100644 index 0000000..cb7ea68 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/copy-texture.md @@ -0,0 +1,19 @@ +# D3D12CommandList::CopyTexture + +```cpp +void CopyTexture(ID3D12Resource* dst, const D3D12_TEXTURE_COPY_LOCATION& dstLocation, ID3D12Resource* src, const D3D12_TEXTURE_COPY_LOCATION& srcLocation); +``` + +复制纹理。 + +**参数:** +- `dst` - 目标纹理 +- `dstLocation` - 目标位置 +- `src` - 源纹理 +- `srcLocation` - 源位置 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/dispatch-indirect.md b/docs/api/rhi/d3d12/command-list/dispatch-indirect.md new file mode 100644 index 0000000..ab5cf17 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/dispatch-indirect.md @@ -0,0 +1,17 @@ +# D3D12CommandList::DispatchIndirect + +```cpp +void DispatchIndirect(void* argBuffer, uint64_t alignedByteOffset); +``` + +间接分发计算命令。 + +**参数:** +- `argBuffer` - 参数缓冲区 +- `alignedByteOffset` - 字节偏移 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/dispatch.md b/docs/api/rhi/d3d12/command-list/dispatch.md new file mode 100644 index 0000000..bada401 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/dispatch.md @@ -0,0 +1,18 @@ +# D3D12CommandList::Dispatch + +```cpp +void Dispatch(uint32_t x, uint32_t y, uint32_t z) override; +``` + +分发计算命令。 + +**参数:** +- `x` - X 维度线程组数量 +- `y` - Y 维度线程组数量 +- `z` - Z 维度线程组数量 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/draw-indexed-instanced-indirect.md b/docs/api/rhi/d3d12/command-list/draw-indexed-instanced-indirect.md new file mode 100644 index 0000000..1f0e223 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/draw-indexed-instanced-indirect.md @@ -0,0 +1,17 @@ +# D3D12CommandList::DrawIndexedInstancedIndirect + +```cpp +void DrawIndexedInstancedIndirect(void* argBuffer, uint64_t alignedByteOffset); +``` + +间接绘制索引实例。 + +**参数:** +- `argBuffer` - 参数缓冲区 +- `alignedByteOffset` - 字节偏移 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/draw-indexed.md b/docs/api/rhi/d3d12/command-list/draw-indexed.md new file mode 100644 index 0000000..24b54e0 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/draw-indexed.md @@ -0,0 +1,20 @@ +# D3D12CommandList::DrawIndexed + +```cpp +void DrawIndexed(uint32_t indexCount, uint32_t instanceCount = 1, uint32_t startIndex = 0, int32_t baseVertex = 0, uint32_t startInstance = 0) override; +``` + +绘制索引调用。 + +**参数:** +- `indexCount` - 索引数量 +- `instanceCount` - 实例数量 +- `startIndex` - 起始索引 +- `baseVertex` - 基础顶点偏移 +- `startInstance` - 起始实例索引 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/draw-instanced-indirect.md b/docs/api/rhi/d3d12/command-list/draw-instanced-indirect.md new file mode 100644 index 0000000..9e44856 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/draw-instanced-indirect.md @@ -0,0 +1,17 @@ +# D3D12CommandList::DrawInstancedIndirect + +```cpp +void DrawInstancedIndirect(void* argBuffer, uint64_t alignedByteOffset); +``` + +间接绘制实例。 + +**参数:** +- `argBuffer` - 参数缓冲区 +- `alignedByteOffset` - 字节偏移 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/draw.md b/docs/api/rhi/d3d12/command-list/draw.md new file mode 100644 index 0000000..acfc11c --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/draw.md @@ -0,0 +1,19 @@ +# D3D12CommandList::Draw + +```cpp +void Draw(uint32_t vertexCount, uint32_t instanceCount = 1, uint32_t startVertex = 0, uint32_t startInstance = 0) override; +``` + +绘制调用。 + +**参数:** +- `vertexCount` - 顶点数量 +- `instanceCount` - 实例数量 +- `startVertex` - 起始顶点索引 +- `startInstance` - 起始实例索引 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/end-query.md b/docs/api/rhi/d3d12/command-list/end-query.md new file mode 100644 index 0000000..f8bde2a --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/end-query.md @@ -0,0 +1,18 @@ +# D3D12CommandList::EndQuery + +```cpp +void EndQuery(ID3D12QueryHeap* queryHeap, QueryType type, uint32_t index); +``` + +结束查询。 + +**参数:** +- `queryHeap` - 查询堆 +- `type` - 查询类型 +- `index` - 查询索引 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/execute-bundle.md b/docs/api/rhi/d3d12/command-list/execute-bundle.md new file mode 100644 index 0000000..0ddd68f --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/execute-bundle.md @@ -0,0 +1,16 @@ +# D3D12CommandList::ExecuteBundle + +```cpp +void ExecuteBundle(ID3D12GraphicsCommandList* bundle); +``` + +执行 Bundle。 + +**参数:** +- `bundle` - Bundle 命令列表 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/get-command-list.md b/docs/api/rhi/d3d12/command-list/get-command-list.md new file mode 100644 index 0000000..0743814 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/get-command-list.md @@ -0,0 +1,15 @@ +# D3D12CommandList::GetCommandList + +```cpp +ID3D12GraphicsCommandList* GetCommandList() const { return m_commandList.Get(); } +``` + +获取底层的 D3D12 图形命令列表接口。 + +**返回:** `ID3D12GraphicsCommandList*` + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/get-resource-state.md b/docs/api/rhi/d3d12/command-list/get-resource-state.md new file mode 100644 index 0000000..81f3d2a --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/get-resource-state.md @@ -0,0 +1,18 @@ +# D3D12CommandList::GetResourceState + +```cpp +ResourceStates GetResourceState(ID3D12Resource* resource) const; +``` + +获取资源状态。 + +**参数:** +- `resource` - D3D12 资源指针 + +**返回:** 资源当前状态 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/resolve-query-data.md b/docs/api/rhi/d3d12/command-list/resolve-query-data.md new file mode 100644 index 0000000..df1e241 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/resolve-query-data.md @@ -0,0 +1,21 @@ +# D3D12CommandList::ResolveQueryData + +```cpp +void ResolveQueryData(ID3D12QueryHeap* queryHeap, QueryType type, uint32_t startIndex, uint32_t count, ID3D12Resource* resultBuffer, uint64_t resultOffset); +``` + +解析查询数据。 + +**参数:** +- `queryHeap` - 查询堆 +- `type` - 查询类型 +- `startIndex` - 起始索引 +- `count` - 查询数量 +- `resultBuffer` - 结果缓冲区 +- `resultOffset` - 结果偏移 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-blend-factor.md b/docs/api/rhi/d3d12/command-list/set-blend-factor.md new file mode 100644 index 0000000..5553f75 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-blend-factor.md @@ -0,0 +1,16 @@ +# D3D12CommandList::SetBlendFactor + +```cpp +void SetBlendFactor(const float blendFactor[4]); +``` + +设置混合因子。 + +**参数:** +- `blendFactor` - 混合因子数组 [r, g, b, a] + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-compute-descriptor-table.md b/docs/api/rhi/d3d12/command-list/set-compute-descriptor-table.md new file mode 100644 index 0000000..b2ffe15 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-compute-descriptor-table.md @@ -0,0 +1,17 @@ +# D3D12CommandList::SetComputeDescriptorTable + +```cpp +void SetComputeDescriptorTable(uint32_t rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE baseHandle); +``` + +设置计算描述符表。 + +**参数:** +- `rootParameterIndex` - 根参数索引 +- `baseHandle` - GPU 描述符句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-depth-bias.md b/docs/api/rhi/d3d12/command-list/set-depth-bias.md new file mode 100644 index 0000000..55dd006 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-depth-bias.md @@ -0,0 +1,18 @@ +# D3D12CommandList::SetDepthBias + +```cpp +void SetDepthBias(float depthBias, float slopeScaledDepthBias, float depthBiasClamp); +``` + +设置深度偏移。 + +**参数:** +- `depthBias` - 基础深度偏移 +- `slopeScaledDepthBias` - 斜率缩放深度偏移 +- `depthBiasClamp` - 深度偏移上限 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-descriptor-heap.md b/docs/api/rhi/d3d12/command-list/set-descriptor-heap.md new file mode 100644 index 0000000..d4a4b48 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-descriptor-heap.md @@ -0,0 +1,16 @@ +# D3D12CommandList::SetDescriptorHeap + +```cpp +void SetDescriptorHeap(ID3D12DescriptorHeap* heap); +``` + +设置描述符堆。 + +**参数:** +- `heap` - D3D12 描述符堆指针 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-descriptor-heaps.md b/docs/api/rhi/d3d12/command-list/set-descriptor-heaps.md new file mode 100644 index 0000000..a3d1eac --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-descriptor-heaps.md @@ -0,0 +1,17 @@ +# D3D12CommandList::SetDescriptorHeaps + +```cpp +void SetDescriptorHeaps(uint32_t count, ID3D12DescriptorHeap** heaps); +``` + +设置多个描述符堆。 + +**参数:** +- `count` - 描述符堆数量 +- `heaps` - 描述符堆指针数组 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-graphics-descriptor-table.md b/docs/api/rhi/d3d12/command-list/set-graphics-descriptor-table.md new file mode 100644 index 0000000..51c21b8 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-graphics-descriptor-table.md @@ -0,0 +1,17 @@ +# D3D12CommandList::SetGraphicsDescriptorTable + +```cpp +void SetGraphicsDescriptorTable(uint32_t rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE baseHandle); +``` + +设置图形描述符表。 + +**参数:** +- `rootParameterIndex` - 根参数索引 +- `baseHandle` - GPU 描述符句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-graphics-root-32bit-constants.md b/docs/api/rhi/d3d12/command-list/set-graphics-root-32bit-constants.md new file mode 100644 index 0000000..ba7b676 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-graphics-root-32bit-constants.md @@ -0,0 +1,19 @@ +# D3D12CommandList::SetGraphicsRoot32BitConstants + +```cpp +void SetGraphicsRoot32BitConstants(uint32_t rootParameterIndex, uint32_t num32BitValuesToSet, const void* pSrcData, uint32_t destOffsetIn32BitValues); +``` + +设置图形根 32 位常量。 + +**参数:** +- `rootParameterIndex` - 根参数索引 +- `num32BitValuesToSet` - 要设置的 32 位值数量 +- `pSrcData` - 源数据指针 +- `destOffsetIn32BitValues` - 目标偏移量 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-graphics-root-constant-buffer-view.md b/docs/api/rhi/d3d12/command-list/set-graphics-root-constant-buffer-view.md new file mode 100644 index 0000000..82b4aab --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-graphics-root-constant-buffer-view.md @@ -0,0 +1,17 @@ +# D3D12CommandList::SetGraphicsRootConstantBufferView + +```cpp +void SetGraphicsRootConstantBufferView(uint32_t rootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS bufferLocation); +``` + +设置图形根常量缓冲区视图。 + +**参数:** +- `rootParameterIndex` - 根参数索引 +- `bufferLocation` - GPU 虚拟地址 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-graphics-root-descriptor-table.md b/docs/api/rhi/d3d12/command-list/set-graphics-root-descriptor-table.md new file mode 100644 index 0000000..5d17a3f --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-graphics-root-descriptor-table.md @@ -0,0 +1,17 @@ +# D3D12CommandList::SetGraphicsRootDescriptorTable + +```cpp +void SetGraphicsRootDescriptorTable(uint32_t rootParameterIndex, D3D12_GPU_DESCRIPTOR_HANDLE baseDescriptor); +``` + +设置图形根描述符表。 + +**参数:** +- `rootParameterIndex` - 根参数索引 +- `baseDescriptor` - GPU 描述符句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-graphics-root-shader-resource-view.md b/docs/api/rhi/d3d12/command-list/set-graphics-root-shader-resource-view.md new file mode 100644 index 0000000..4dd985d --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-graphics-root-shader-resource-view.md @@ -0,0 +1,17 @@ +# D3D12CommandList::SetGraphicsRootShaderResourceView + +```cpp +void SetGraphicsRootShaderResourceView(uint32_t rootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS shaderResource); +``` + +设置图形根着色器资源视图。 + +**参数:** +- `rootParameterIndex` - 根参数索引 +- `shaderResource` - GPU 虚拟地址 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-index-buffer.md b/docs/api/rhi/d3d12/command-list/set-index-buffer.md new file mode 100644 index 0000000..45a2602 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-index-buffer.md @@ -0,0 +1,18 @@ +# D3D12CommandList::SetIndexBuffer + +```cpp +void SetIndexBuffer(void* buffer, uint64_t offset, Format format) override; +``` + +设置索引缓冲区。 + +**参数:** +- `buffer` - 缓冲区指针 +- `offset` - 缓冲区偏移 +- `format` - 索引格式 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-pipeline-state.md b/docs/api/rhi/d3d12/command-list/set-pipeline-state.md new file mode 100644 index 0000000..d05ac7c --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-pipeline-state.md @@ -0,0 +1,16 @@ +# D3D12CommandList::SetPipelineState + +```cpp +void SetPipelineState(void* pso) override; +``` + +设置图形管线状态对象。 + +**参数:** +- `pso` - 管线状态对象指针 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-primitive-topology.md b/docs/api/rhi/d3d12/command-list/set-primitive-topology.md new file mode 100644 index 0000000..a8e13ac --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-primitive-topology.md @@ -0,0 +1,16 @@ +# D3D12CommandList::SetPrimitiveTopology + +```cpp +void SetPrimitiveTopology(PrimitiveTopology topology); +``` + +设置图元拓扑类型。 + +**参数:** +- `topology` - 图元拓扑类型 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-render-targets-handle.md b/docs/api/rhi/d3d12/command-list/set-render-targets-handle.md new file mode 100644 index 0000000..45081f7 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-render-targets-handle.md @@ -0,0 +1,18 @@ +# D3D12CommandList::SetRenderTargetsHandle + +```cpp +void SetRenderTargetsHandle(uint32_t count, const D3D12_CPU_DESCRIPTOR_HANDLE* renderTargetHandles, const D3D12_CPU_DESCRIPTOR_HANDLE* depthStencilHandle = nullptr); +``` + +使用描述符句柄设置渲染目标。 + +**参数:** +- `count` - 渲染目标数量 +- `renderTargetHandles` - 渲染目标描述符句柄数组 +- `depthStencilHandle` - 深度模板描述符句柄 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-render-targets-internal.md b/docs/api/rhi/d3d12/command-list/set-render-targets-internal.md new file mode 100644 index 0000000..6ea787d --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-render-targets-internal.md @@ -0,0 +1,18 @@ +# D3D12CommandList::SetRenderTargetsInternal + +```cpp +void SetRenderTargetsInternal(uint32_t count, ID3D12Resource** renderTargets, ID3D12Resource* depthStencil = nullptr); +``` + +设置渲染目标(内部接口)。 + +**参数:** +- `count` - 渲染目标数量 +- `renderTargets` - D3D12 资源指针数组 +- `depthStencil` - 深度模板资源指针 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-render-targets.md b/docs/api/rhi/d3d12/command-list/set-render-targets.md new file mode 100644 index 0000000..d64ea5a --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-render-targets.md @@ -0,0 +1,18 @@ +# D3D12CommandList::SetRenderTargets + +```cpp +void SetRenderTargets(uint32_t count, void** renderTargets, void* depthStencil = nullptr) override; +``` + +设置渲染目标。 + +**参数:** +- `count` - 渲染目标数量 +- `renderTargets` - 渲染目标指针数组 +- `depthStencil` - 深度模板目标指针 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-root-signature.md b/docs/api/rhi/d3d12/command-list/set-root-signature.md new file mode 100644 index 0000000..0593c1e --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-root-signature.md @@ -0,0 +1,16 @@ +# D3D12CommandList::SetRootSignature + +```cpp +void SetRootSignature(ID3D12RootSignature* signature); +``` + +设置根签名。 + +**参数:** +- `signature` - D3D12 根签名指针 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-scissor-rect.md b/docs/api/rhi/d3d12/command-list/set-scissor-rect.md new file mode 100644 index 0000000..c01ba97 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-scissor-rect.md @@ -0,0 +1,16 @@ +# D3D12CommandList::SetScissorRect + +```cpp +void SetScissorRect(const Rect& rect) override; +``` + +设置裁剪矩形。 + +**参数:** +- `rect` - 裁剪矩形结构 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-scissor-rects.md b/docs/api/rhi/d3d12/command-list/set-scissor-rects.md new file mode 100644 index 0000000..4745112 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-scissor-rects.md @@ -0,0 +1,17 @@ +# D3D12CommandList::SetScissorRects + +```cpp +void SetScissorRects(uint32_t count, const Rect* rects) override; +``` + +设置多个裁剪矩形。 + +**参数:** +- `count` - 裁剪矩形数量 +- `rects` - 裁剪矩形数组 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-stencil-ref.md b/docs/api/rhi/d3d12/command-list/set-stencil-ref.md new file mode 100644 index 0000000..88bbf00 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-stencil-ref.md @@ -0,0 +1,16 @@ +# D3D12CommandList::SetStencilRef + +```cpp +void SetStencilRef(uint32_t stencilRef); +``` + +设置模板参考值。 + +**参数:** +- `stencilRef` - 模板参考值 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-vertex-buffer.md b/docs/api/rhi/d3d12/command-list/set-vertex-buffer.md new file mode 100644 index 0000000..8811d8c --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-vertex-buffer.md @@ -0,0 +1,19 @@ +# D3D12CommandList::SetVertexBuffer + +```cpp +void SetVertexBuffer(uint32_t slot, void* buffer, uint64_t offset, uint32_t stride) override; +``` + +设置单个顶点缓冲区。 + +**参数:** +- `slot` - 顶点缓冲区槽位 +- `buffer` - 缓冲区指针 +- `offset` - 缓冲区偏移 +- `stride` - 顶点 stride + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-vertex-buffers.md b/docs/api/rhi/d3d12/command-list/set-vertex-buffers.md new file mode 100644 index 0000000..faedf0c --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-vertex-buffers.md @@ -0,0 +1,20 @@ +# D3D12CommandList::SetVertexBuffers + +```cpp +void SetVertexBuffers(uint32_t startSlot, uint32_t count, const uint64_t* buffers, const uint64_t* offsets, const uint32_t* strides) override; +``` + +设置多个顶点缓冲区。 + +**参数:** +- `startSlot` - 起始槽位 +- `count` - 缓冲区数量 +- `buffers` - 缓冲区指针数组 +- `offsets` - 偏移数组 +- `strides` - stride 数组 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-viewport.md b/docs/api/rhi/d3d12/command-list/set-viewport.md new file mode 100644 index 0000000..7331fa7 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-viewport.md @@ -0,0 +1,16 @@ +# D3D12CommandList::SetViewport + +```cpp +void SetViewport(const Viewport& viewport) override; +``` + +设置视口。 + +**参数:** +- `viewport` - 视口结构 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/set-viewports.md b/docs/api/rhi/d3d12/command-list/set-viewports.md new file mode 100644 index 0000000..a84791e --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/set-viewports.md @@ -0,0 +1,17 @@ +# D3D12CommandList::SetViewports + +```cpp +void SetViewports(uint32_t count, const Viewport* viewports) override; +``` + +设置多个视口。 + +**参数:** +- `count` - 视口数量 +- `viewports` - 视口数组 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/track-resource.md b/docs/api/rhi/d3d12/command-list/track-resource.md new file mode 100644 index 0000000..b950204 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/track-resource.md @@ -0,0 +1,16 @@ +# D3D12CommandList::TrackResource + +```cpp +void TrackResource(ID3D12Resource* resource); +``` + +跟踪资源状态。 + +**参数:** +- `resource` - D3D12 资源指针 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/transition-barrier-internal.md b/docs/api/rhi/d3d12/command-list/transition-barrier-internal.md new file mode 100644 index 0000000..ef03d8f --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/transition-barrier-internal.md @@ -0,0 +1,19 @@ +# D3D12CommandList::TransitionBarrierInternal + +```cpp +void TransitionBarrierInternal(ID3D12Resource* resource, ResourceStates stateBefore, ResourceStates stateAfter, uint32_t subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES); +``` + +为资源添加转换屏障(内部接口)。 + +**参数:** +- `resource` - D3D12 资源指针 +- `stateBefore` - 转换前的资源状态 +- `stateAfter` - 转换后的资源状态 +- `subresource` - 子资源索引,默认为所有子资源 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/transition-barrier.md b/docs/api/rhi/d3d12/command-list/transition-barrier.md new file mode 100644 index 0000000..49166c3 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/transition-barrier.md @@ -0,0 +1,18 @@ +# D3D12CommandList::TransitionBarrier + +```cpp +void TransitionBarrier(void* resource, ResourceStates stateBefore, ResourceStates stateAfter) override; +``` + +为资源添加转换屏障。 + +**参数:** +- `resource` - 目标资源指针 +- `stateBefore` - 转换前的资源状态 +- `stateAfter` - 转换后的资源状态 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-list/uav-barrier.md b/docs/api/rhi/d3d12/command-list/uav-barrier.md new file mode 100644 index 0000000..c2536e9 --- /dev/null +++ b/docs/api/rhi/d3d12/command-list/uav-barrier.md @@ -0,0 +1,16 @@ +# D3D12CommandList::UAVBarrier + +```cpp +void UAVBarrier(void* resource = nullptr); +``` + +添加无序访问视图屏障。 + +**参数:** +- `resource` - 目标资源指针,nullptr 表示所有 UAV + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-queue/command-queue.md b/docs/api/rhi/d3d12/command-queue/command-queue.md new file mode 100644 index 0000000..c717e41 --- /dev/null +++ b/docs/api/rhi/d3d12/command-queue/command-queue.md @@ -0,0 +1,26 @@ +# D3D12CommandQueue + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 命令队列的 D3D12 实现,继承自 `RHICommandQueue`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化命令队列 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭命令队列 | +| [`ExecuteCommandLists`](execute-command-lists.md) | 执行命令列表 | +| [`Signal`](signal.md) | 信号栅栏 | +| [`Wait`](../../../threading/task-group/wait.md) | 等待栅栏 | +| [`GetCompletedValue`](get-completed-value.md) | 获取完成值 | +| [`WaitForIdle`](wait-for-idle.md) | 等待空闲 | +| [`GetType`](../../command-queue/get-type.md) | 获取队列类型 | +| [`GetTimestampFrequency`](get-timestamp-frequency.md) | 获取时间戳频率 | +| [`GetCommandQueue`](get-command-queue.md) | 获取 D3D12 命令队列 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) +- [RHICommandQueue](../../command-queue/command-queue.md) - 抽象命令队列接口 diff --git a/docs/api/rhi/d3d12/command-queue/execute-command-lists.md b/docs/api/rhi/d3d12/command-queue/execute-command-lists.md new file mode 100644 index 0000000..ca08fc3 --- /dev/null +++ b/docs/api/rhi/d3d12/command-queue/execute-command-lists.md @@ -0,0 +1,17 @@ +# D3D12CommandQueue::ExecuteCommandLists + +```cpp +void ExecuteCommandLists(uint32_t count, void** lists) override; +``` + +执行命令列表。 + +**参数:** +- `count` - 命令列表数量 +- `lists` - 命令列表指针数组 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-queue/get-command-queue.md b/docs/api/rhi/d3d12/command-queue/get-command-queue.md new file mode 100644 index 0000000..90176f0 --- /dev/null +++ b/docs/api/rhi/d3d12/command-queue/get-command-queue.md @@ -0,0 +1,15 @@ +# D3D12CommandQueue::GetCommandQueue + +```cpp +ID3D12CommandQueue* GetCommandQueue() const { return m_commandQueue.Get(); } +``` + +获取底层 D3D12 命令队列接口。 + +**返回:** `ID3D12CommandQueue*` + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-queue/get-completed-value.md b/docs/api/rhi/d3d12/command-queue/get-completed-value.md new file mode 100644 index 0000000..f649b7d --- /dev/null +++ b/docs/api/rhi/d3d12/command-queue/get-completed-value.md @@ -0,0 +1,15 @@ +# D3D12CommandQueue::GetCompletedValue + +```cpp +uint64_t GetCompletedValue() override; +``` + +获取已完成值。 + +**返回:** 栅栏已完成的值 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-queue/get-timestamp-frequency.md b/docs/api/rhi/d3d12/command-queue/get-timestamp-frequency.md new file mode 100644 index 0000000..187a99b --- /dev/null +++ b/docs/api/rhi/d3d12/command-queue/get-timestamp-frequency.md @@ -0,0 +1,15 @@ +# D3D12CommandQueue::GetTimestampFrequency + +```cpp +uint64_t GetTimestampFrequency() const override { return m_timestampFrequency; } +``` + +获取时间戳频率。 + +**返回:** 时间戳频率 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-queue/signal.md b/docs/api/rhi/d3d12/command-queue/signal.md new file mode 100644 index 0000000..b1ec265 --- /dev/null +++ b/docs/api/rhi/d3d12/command-queue/signal.md @@ -0,0 +1,17 @@ +# D3D12CommandQueue::Signal + +```cpp +void Signal(RHIFence* fence, uint64_t value) override; +``` + +发送信号。 + +**参数:** +- `fence` - 栅栏指针 +- `value` - 信号值 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12CommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/command-queue/wait-for-idle.md b/docs/api/rhi/d3d12/command-queue/wait-for-idle.md new file mode 100644 index 0000000..71c0f4b --- /dev/null +++ b/docs/api/rhi/d3d12/command-queue/wait-for-idle.md @@ -0,0 +1,13 @@ +# D3D12CommandQueue::WaitForIdle + +```cpp +void WaitForIdle() override; +``` + +等待空闲。 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12CommandQueue 总览](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/common/common.md b/docs/api/rhi/d3d12/common/common.md new file mode 100644 index 0000000..0c94b9b --- /dev/null +++ b/docs/api/rhi/d3d12/common/common.md @@ -0,0 +1,67 @@ +# D3D12Common + +**命名空间**: `XCEngine::RHI` + +**描述**: D3D12 通用辅助函数集合,提供描述符大小、屏障创建、格式支持检查等功能。**所有函数均为 inline 函数**。 + +## 函数列表 + +### 描述符大小 + +| 函数 | 描述 | +|------|------| +| `GetDescriptorHandleIncrementSize` | 获取描述符增量大小 | +| `GetRTVDescriptorSize` | 获取 RTV 描述符大小 | +| `GetDSVDescriptorSize` | 获取 DSV 描述符大小 | +| `GetCBV_SRV_UAVDescriptorSize` | 获取 CBV/SRV/UAV 描述符大小 | +| `GetSamplerDescriptorSize` | 获取 Sampler 描述符大小 | + +### 屏障创建 + +| 函数 | 描述 | +|------|------| +| `CreateTransitionBarrier` | 创建资源状态转换屏障 | +| `CreateUAVBarrier` | 创建 UAV 屏障 | +| `CreateAliasingBarrier` | 创建别名化屏障 | + +### 格式支持 + +| 函数 | 描述 | +|------|------| +| `CheckFormatSupport` | 检查格式支持 | +| `IsRenderTargetFormatSupported` | 检查是否支持作为渲染目标 | +| `IsDepthStencilFormatSupported` | 检查是否支持作为深度模板 | +| `IsShaderResourceFormatSupported` | 检查 shader 是否可读取 | +| `IsTextureFormatSupported` | 检查是否支持作为纹理 | + +### 清除值创建 + +| 函数 | 描述 | +|------|------| +| `CreateRenderTargetClearValue` | 创建渲染目标清除值 | +| `CreateDepthStencilClearValue` | 创建深度模板清除值 | + +### 视口和裁剪矩形 + +| 函数 | 描述 | +|------|------| +| `CreateViewport` | 创建视口 | +| `CreateScissorRect` | 创建裁剪矩形 | + +### 缓冲区视图 + +| 函数 | 描述 | +|------|------| +| `CreateVertexBufferView` | 创建顶点缓冲区视图 | +| `CreateIndexBufferView` | 创建索引缓冲区视图 | + +### 描述符句柄运算 + +| 函数 | 描述 | +|------|------| +| `GetCPUDescriptorHandle` | 计算偏移后的 CPU 描述符句柄 | +| `GetGPUDescriptorHandle` | 计算偏移后的 GPU 描述符句柄 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) diff --git a/docs/api/rhi/d3d12/constant-buffer-view/constant-buffer-view.md b/docs/api/rhi/d3d12/constant-buffer-view/constant-buffer-view.md new file mode 100644 index 0000000..f59eb66 --- /dev/null +++ b/docs/api/rhi/d3d12/constant-buffer-view/constant-buffer-view.md @@ -0,0 +1,17 @@ +# D3D12ConstantBufferView + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 常量缓冲区视图的 D3D12 实现。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化常量缓冲区视图 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭常量缓冲区视图 | +| [`GetCPUDescriptorHandle`](get-cpu-descriptor-handle.md) | 获取 CPU 描述符句柄 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) diff --git a/docs/api/rhi/d3d12/constant-buffer-view/get-cpu-descriptor-handle.md b/docs/api/rhi/d3d12/constant-buffer-view/get-cpu-descriptor-handle.md new file mode 100644 index 0000000..c4202e6 --- /dev/null +++ b/docs/api/rhi/d3d12/constant-buffer-view/get-cpu-descriptor-handle.md @@ -0,0 +1,15 @@ +# D3D12ConstantBufferView::GetCPUDescriptorHandle + +```cpp +D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() const { return m_handle; } +``` + +获取 CPU 描述符句柄。 + +**返回:** CPU 描述符句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12ConstantBufferView 总览](constant-buffer-view.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/d3d12.md b/docs/api/rhi/d3d12/d3d12.md new file mode 100644 index 0000000..74a5088 --- /dev/null +++ b/docs/api/rhi/d3d12/d3d12.md @@ -0,0 +1,77 @@ +# D3D12 后端概览 + +**命名空间**: `XCEngine::RHI` + +**类型**: `module` + +**描述**: DirectX 12 后端实现模块,提供对 DirectX 12 API 的完整封装。 + +## 组件列表 + +### 核心组件 + +| 组件 | 文档 | +|------|------| +| [D3D12Device](device/device.md) | DirectX 12 设备实现 | +| [D3D12CommandList](command-list/command-list.md) | 命令列表实现 | + +### 资源类型 + +| 组件 | 文档 | +|------|------| +| [D3D12Buffer](buffer/buffer.md) | GPU 缓冲区实现 | +| [D3D12Texture](texture/texture.md) | GPU 纹理实现 | + +### 命令执行 + +| 组件 | 文档 | +|------|------| +| [D3D12CommandQueue](command-queue/command-queue.md) | 命令队列实现 | +| [D3D12CommandAllocator](command-allocator/command-allocator.md) | 命令分配器 | + +### 同步原语 + +| 组件 | 文档 | +|------|------| +| [D3D12Fence](fence/fence.md) | 同步栅栏实现 | +| [D3D12SwapChain](swap-chain/swap-chain.md) | 交换链实现 | + +### 渲染状态 + +| 组件 | 文档 | +|------|------| +| [D3D12Shader](shader/shader.md) | 着色器实现 | +| [D3D12PipelineState](pipeline-state/pipeline-state.md) | 管线状态对象 | +| [D3D12Sampler](sampler/sampler.md) | 采样器实现 | +| [D3D12RootSignature](root-signature/root-signature.md) | 根签名实现 | + +### 描述符 + +| 组件 | 文档 | +|------|------| +| [D3D12DescriptorHeap](descriptor-heap/descriptor-heap.md) | 描述符堆实现 | +| [D3D12RenderTargetView](render-target-view/render-target-view.md) | 渲染目标视图 | +| [D3D12DepthStencilView](depth-stencil-view/depth-stencil-view.md) | 深度模板视图 | +| [D3D12ShaderResourceView](shader-resource-view/shader-resource-view.md) | 着色器资源视图 | +| [D3D12UnorderedAccessView](unordered-access-view/unordered-access-view.md) | 无序访问视图 | +| [D3D12ConstantBufferView](constant-buffer-view/constant-buffer-view.md) | 常量缓冲视图 | + +### 查询 + +| 组件 | 文档 | +|------|------| +| [D3D12QueryHeap](query-heap/query-heap.md) | 查询堆实现 | + +### 工具 + +| 组件 | 文档 | +|------|------| +| [D3D12Screenshot](screenshot/screenshot.md) | 截图工具 | +| [D3D12Types](types/types.md) | D3D12 类型转换 | +| [D3D12Enums](enums/enums.md) | D3D12 枚举转换 | +| [D3D12Common](common/common.md) | D3D12 公共工具函数 | + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [OpenGL 后端](../opengl/overview.md) diff --git a/docs/api/rhi/d3d12/depth-stencil-view/create-desc.md b/docs/api/rhi/d3d12/depth-stencil-view/create-desc.md new file mode 100644 index 0000000..5f36d14 --- /dev/null +++ b/docs/api/rhi/d3d12/depth-stencil-view/create-desc.md @@ -0,0 +1,19 @@ +# D3D12DepthStencilView::CreateDesc + +```cpp +static D3D12_DEPTH_STENCIL_VIEW_DESC CreateDesc(Format format, D3D12_DSV_DIMENSION dimension = D3D12_DSV_DIMENSION_TEXTURE2D); +``` + +创建深度模板视图描述(静态方法)。 + +**参数:** +- `format` - 格式 +- `dimension` - 视图维度 + +**返回:** D3D12 深度模板视图描述 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12DepthStencilView 总览](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/depth-stencil-view/depth-stencil-view.md b/docs/api/rhi/d3d12/depth-stencil-view/depth-stencil-view.md new file mode 100644 index 0000000..e528ab1 --- /dev/null +++ b/docs/api/rhi/d3d12/depth-stencil-view/depth-stencil-view.md @@ -0,0 +1,19 @@ +# D3D12DepthStencilView + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 深度模板视图的 D3D12 实现。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化深度模板视图 | +| [`InitializeAt`](initialize-at.md) | 在指定位置初始化 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭深度模板视图 | +| [`GetCPUDescriptorHandle`](get-cpu-descriptor-handle.md) | 获取 CPU 描述符句柄 | +| [`CreateDesc`](create-desc.md) | 创建描述符(静态) | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) diff --git a/docs/api/rhi/d3d12/depth-stencil-view/get-cpu-descriptor-handle.md b/docs/api/rhi/d3d12/depth-stencil-view/get-cpu-descriptor-handle.md new file mode 100644 index 0000000..a956320 --- /dev/null +++ b/docs/api/rhi/d3d12/depth-stencil-view/get-cpu-descriptor-handle.md @@ -0,0 +1,15 @@ +# D3D12DepthStencilView::GetCPUDescriptorHandle + +```cpp +D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() const { return m_handle; } +``` + +获取 CPU 描述符句柄。 + +**返回:** CPU 描述符句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12DepthStencilView 总览](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/depth-stencil-view/initialize-at.md b/docs/api/rhi/d3d12/depth-stencil-view/initialize-at.md new file mode 100644 index 0000000..0ed47b9 --- /dev/null +++ b/docs/api/rhi/d3d12/depth-stencil-view/initialize-at.md @@ -0,0 +1,19 @@ +# D3D12DepthStencilView::InitializeAt + +```cpp +void InitializeAt(ID3D12Device* device, ID3D12Resource* resource, D3D12_CPU_DESCRIPTOR_HANDLE handle, const D3D12_DEPTH_STENCIL_VIEW_DESC* desc = nullptr); +``` + +在指定位置初始化深度模板视图。 + +**参数:** +- `device` - D3D12 设备 +- `resource` - D3D12 资源 +- `handle` - CPU 描述符句柄 +- `desc` - 深度模板视图描述 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12DepthStencilView 总览](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/descriptor-heap/create-desc.md b/docs/api/rhi/d3d12/descriptor-heap/create-desc.md new file mode 100644 index 0000000..a235325 --- /dev/null +++ b/docs/api/rhi/d3d12/descriptor-heap/create-desc.md @@ -0,0 +1,20 @@ +# D3D12DescriptorHeap::CreateDesc + +```cpp +static D3D12_DESCRIPTOR_HEAP_DESC CreateDesc(DescriptorHeapType type, uint32_t numDescriptors, bool shaderVisible = false); +``` + +创建描述符堆描述(静态方法)。 + +**参数:** +- `type` - 描述符堆类型 +- `numDescriptors` - 描述符数量 +- `shaderVisible` - 是否对 Shader 可见 + +**返回:** D3D12 描述符堆描述 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12DescriptorHeap 总览](descriptor-heap.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/descriptor-heap/descriptor-heap.md b/docs/api/rhi/d3d12/descriptor-heap/descriptor-heap.md new file mode 100644 index 0000000..d17ea0f --- /dev/null +++ b/docs/api/rhi/d3d12/descriptor-heap/descriptor-heap.md @@ -0,0 +1,27 @@ +# D3D12DescriptorHeap + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 描述符堆的 D3D12 实现,继承自 `RHIDescriptorPool`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](initialize-from-desc.md) | 从描述符初始化 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭描述符堆 | +| [`GetDescriptorHeap`](get-descriptor-heap.md) | 获取 D3D12 描述符堆 | +| [`GetCPUDescriptorHandle`](get-cpu-descriptor-handle.md) | 获取 CPU 描述符句柄 | +| [`GetGPUDescriptorHandle`](get-gpu-descriptor-handle.md) | 获取 GPU 描述符句柄 | +| [`GetDescriptorCount`](get-descriptor-count.md) | 获取描述符数量 | +| [`GetType`](../../command-queue/get-type.md) | 获取描述符类型 | +| [`GetDescriptorSize`](get-descriptor-size.md) | 获取描述符大小 | +| [`GetCPUDescriptorHandleForHeapStart`](get-cpu-descriptor-handle-for-heap-start.md) | 获取堆起始 CPU 句柄 | +| [`GetGPUDescriptorHandleForHeapStart`](get-gpu-descriptor-handle-for-heap-start.md) | 获取堆起始 GPU 句柄 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | +| [`CreateDesc`](create-desc.md) | 创建描述符(静态) | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) +- [RHIDescriptorPool](../../descriptor-pool/descriptor-pool.md) - 抽象描述符池接口 diff --git a/docs/api/rhi/d3d12/descriptor-heap/get-cpu-descriptor-handle-for-heap-start.md b/docs/api/rhi/d3d12/descriptor-heap/get-cpu-descriptor-handle-for-heap-start.md new file mode 100644 index 0000000..74caa4d --- /dev/null +++ b/docs/api/rhi/d3d12/descriptor-heap/get-cpu-descriptor-handle-for-heap-start.md @@ -0,0 +1,15 @@ +# D3D12DescriptorHeap::GetCPUDescriptorHandleForHeapStart + +```cpp +D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandleForHeapStart() const; +``` + +获取堆起始处的 CPU 描述符句柄。 + +**返回:** CPU 描述符句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12DescriptorHeap 总览](descriptor-heap.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/descriptor-heap/get-cpu-descriptor-handle.md b/docs/api/rhi/d3d12/descriptor-heap/get-cpu-descriptor-handle.md new file mode 100644 index 0000000..af1d9da --- /dev/null +++ b/docs/api/rhi/d3d12/descriptor-heap/get-cpu-descriptor-handle.md @@ -0,0 +1,18 @@ +# D3D12DescriptorHeap::GetCPUDescriptorHandle + +```cpp +CPUDescriptorHandle GetCPUDescriptorHandle(uint32_t index); +``` + +获取 CPU 描述符句柄。 + +**参数:** +- `index` - 描述符索引 + +**返回:** CPU 描述符句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12DescriptorHeap 总览](descriptor-heap.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/descriptor-heap/get-descriptor-count.md b/docs/api/rhi/d3d12/descriptor-heap/get-descriptor-count.md new file mode 100644 index 0000000..027027b --- /dev/null +++ b/docs/api/rhi/d3d12/descriptor-heap/get-descriptor-count.md @@ -0,0 +1,15 @@ +# D3D12DescriptorHeap::GetDescriptorCount + +```cpp +uint32_t GetDescriptorCount() const override; +``` + +获取描述符数量。 + +**返回:** 描述符数量 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12DescriptorHeap 总览](descriptor-heap.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/descriptor-heap/get-descriptor-heap.md b/docs/api/rhi/d3d12/descriptor-heap/get-descriptor-heap.md new file mode 100644 index 0000000..502fbb1 --- /dev/null +++ b/docs/api/rhi/d3d12/descriptor-heap/get-descriptor-heap.md @@ -0,0 +1,15 @@ +# D3D12DescriptorHeap::GetDescriptorHeap + +```cpp +ID3D12DescriptorHeap* GetDescriptorHeap() const { return m_descriptorHeap.Get(); } +``` + +获取底层 D3D12 描述符堆接口。 + +**返回:** `ID3D12DescriptorHeap*` + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12DescriptorHeap 总览](descriptor-heap.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/descriptor-heap/get-descriptor-size.md b/docs/api/rhi/d3d12/descriptor-heap/get-descriptor-size.md new file mode 100644 index 0000000..44e4059 --- /dev/null +++ b/docs/api/rhi/d3d12/descriptor-heap/get-descriptor-size.md @@ -0,0 +1,15 @@ +# D3D12DescriptorHeap::GetDescriptorSize + +```cpp +uint32_t GetDescriptorSize() const { return m_descriptorSize; } +``` + +获取描述符大小。 + +**返回:** 描述符大小(字节) + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12DescriptorHeap 总览](descriptor-heap.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/descriptor-heap/get-gpu-descriptor-handle-for-heap-start.md b/docs/api/rhi/d3d12/descriptor-heap/get-gpu-descriptor-handle-for-heap-start.md new file mode 100644 index 0000000..bc33191 --- /dev/null +++ b/docs/api/rhi/d3d12/descriptor-heap/get-gpu-descriptor-handle-for-heap-start.md @@ -0,0 +1,15 @@ +# D3D12DescriptorHeap::GetGPUDescriptorHandleForHeapStart + +```cpp +D3D12_GPU_DESCRIPTOR_HANDLE GetGPUDescriptorHandleForHeapStart() const; +``` + +获取堆起始处的 GPU 描述符句柄。 + +**返回:** GPU 描述符句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12DescriptorHeap 总览](descriptor-heap.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/descriptor-heap/get-gpu-descriptor-handle.md b/docs/api/rhi/d3d12/descriptor-heap/get-gpu-descriptor-handle.md new file mode 100644 index 0000000..036b472 --- /dev/null +++ b/docs/api/rhi/d3d12/descriptor-heap/get-gpu-descriptor-handle.md @@ -0,0 +1,18 @@ +# D3D12DescriptorHeap::GetGPUDescriptorHandle + +```cpp +GPUDescriptorHandle GetGPUDescriptorHandle(uint32_t index); +``` + +获取 GPU 描述符句柄。 + +**参数:** +- `index` - 描述符索引 + +**返回:** GPU 描述符句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [D3D12DescriptorHeap 总览](descriptor-heap.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/descriptor-heap/initialize-from-desc.md b/docs/api/rhi/d3d12/descriptor-heap/initialize-from-desc.md new file mode 100644 index 0000000..762c261 --- /dev/null +++ b/docs/api/rhi/d3d12/descriptor-heap/initialize-from-desc.md @@ -0,0 +1,18 @@ +# D3D12DescriptorHeap::InitializeFromDesc + +```cpp +bool Initialize(const DescriptorPoolDesc& desc) override; +``` + +从描述符初始化。 + +**参数:** +- `desc` - 描述符池描述 + +**返回:** 是否初始化成功 + +**复杂度:** O(n) + +## 相关文档 + +- [D3D12DescriptorHeap 总览](descriptor-heap.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/device/check-feature-support.md b/docs/api/rhi/d3d12/device/check-feature-support.md new file mode 100644 index 0000000..2947ffb --- /dev/null +++ b/docs/api/rhi/d3d12/device/check-feature-support.md @@ -0,0 +1,25 @@ +# D3D12Device::CheckFeatureSupport + +```cpp +bool CheckFeatureSupport(D3D12_FEATURE feature, void* featureSupportData, uint32_t featureSupportDataSize) +``` + +检查特性支持。 + +**参数:** +- `feature` - 特性类型 +- `featureSupportData` - 特性支持数据缓冲区 +- `featureSupportDataSize` - 数据大小 + +**返回:** 是否支持该特性 + +**示例:** + +```cpp +D3D12_FEATURE_DATA_D3D12_OPTIONS options; +bool supported = d3d12Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)); +``` + +## 相关文档 + +- [D3D12Device 总览](device.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/device/device.md b/docs/api/rhi/d3d12/device/device.md new file mode 100644 index 0000000..ac1b59c --- /dev/null +++ b/docs/api/rhi/d3d12/device/device.md @@ -0,0 +1,35 @@ +# D3D12Device + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 设备实现,继承自 `RHIDevice`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化设备 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭设备 | +| [`CreateBuffer`](../../device/create-buffer.md) | 创建缓冲区 | +| [`CreateTexture`](../../device/create-texture.md) | 创建纹理 | +| [`CreateSwapChain`](../../device/create-swap-chain.md) | 创建交换链 | +| [`CreateCommandList`](../../device/create-command-list.md) | 创建命令列表 | +| [`CreateCommandQueue`](../../device/create-command-queue.md) | 创建命令队列 | +| [`CompileShader`](../../device/compile-shader.md) | 编译着色器 | +| [`CreatePipelineState`](../../device/create-pipeline-state.md) | 创建管线状态 | +| [`CreateFence`](../../device/create-fence.md) | 创建栅栏 | +| [`CreateSampler`](../../device/create-sampler.md) | 创建采样器 | +| [`GetCapabilities`](../../device/get-capabilities.md) | 获取设备能力 | +| [`GetDeviceInfo`](../../device/get-device-info.md) | 获取设备信息 | +| [`GetNativeDevice`](../../device/get-native-device.md) | 获取原生设备 | +| [`GetDevice`](get-device.md) | 获取 D3D12 设备 | +| [`GetFactory`](get-factory.md) | 获取 D3D12 工厂 | +| [`GetAdapterInfo`](get-adapter-info.md) | 获取适配器信息 | +| [`EnumerateAdapters`](enumerate-adapters.md) | 枚举适配器 | +| [`GetDescriptorHandleIncrementSize`](get-descriptor-handle-increment-size.md) | 获取描述符增量大小 | +| [`CheckFeatureSupport`](check-feature-support.md) | 检查特性支持 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) +- [RHIDevice](../../device/device.md) - 抽象设备接口 diff --git a/docs/api/rhi/d3d12/device/enumerate-adapters.md b/docs/api/rhi/d3d12/device/enumerate-adapters.md new file mode 100644 index 0000000..a26b40b --- /dev/null +++ b/docs/api/rhi/d3d12/device/enumerate-adapters.md @@ -0,0 +1,22 @@ +# D3D12Device::EnumerateAdapters + +```cpp +std::vector EnumerateAdapters() +``` + +枚举所有可用的图形适配器。 + +**返回:** 适配器信息列表 + +**示例:** + +```cpp +std::vector adapters = d3d12Device->EnumerateAdapters(); +for (const auto& adapter : adapters) { + wprintf(L"Adapter: %ls\n", adapter.description.c_str()); +} +``` + +## 相关文档 + +- [D3D12Device 总览](device.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/device/get-adapter-info.md b/docs/api/rhi/d3d12/device/get-adapter-info.md new file mode 100644 index 0000000..18fa355 --- /dev/null +++ b/docs/api/rhi/d3d12/device/get-adapter-info.md @@ -0,0 +1,20 @@ +# D3D12Device::GetAdapterInfo + +```cpp +const AdapterInfo& GetAdapterInfo() const +``` + +获取适配器信息。 + +**返回:** 适配器信息结构体引用 + +**示例:** + +```cpp +const AdapterInfo& info = d3d12Device->GetAdapterInfo(); +wprintf(L"GPU: %ls\n", info.description.c_str()); +``` + +## 相关文档 + +- [D3D12Device 总览](device.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/device/get-descriptor-handle-increment-size.md b/docs/api/rhi/d3d12/device/get-descriptor-handle-increment-size.md new file mode 100644 index 0000000..2123bf5 --- /dev/null +++ b/docs/api/rhi/d3d12/device/get-descriptor-handle-increment-size.md @@ -0,0 +1,22 @@ +# D3D12Device::GetDescriptorHandleIncrementSize + +```cpp +UINT GetDescriptorHandleIncrementSize(DescriptorHeapType type) const +``` + +获取描述符句柄增量大小。 + +**参数:** +- `type` - 描述符堆类型 + +**返回:** 描述符句柄增量大小(字节) + +**示例:** + +```cpp +UINT size = d3d12Device->GetDescriptorHandleIncrementSize(DescriptorHeapType::CBV_SRV_UAV); +``` + +## 相关文档 + +- [D3D12Device 总览](device.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/device/get-device.md b/docs/api/rhi/d3d12/device/get-device.md new file mode 100644 index 0000000..df08ac4 --- /dev/null +++ b/docs/api/rhi/d3d12/device/get-device.md @@ -0,0 +1,19 @@ +# D3D12Device::GetDevice + +```cpp +ID3D12Device* GetDevice() const +``` + +获取底层 D3D12 设备指针。 + +**返回:** DirectX 12 设备指针 + +**示例:** + +```cpp +ID3D12Device* device = d3d12Device->GetDevice(); +``` + +## 相关文档 + +- [D3D12Device 总览](device.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/device/get-factory.md b/docs/api/rhi/d3d12/device/get-factory.md new file mode 100644 index 0000000..b90675a --- /dev/null +++ b/docs/api/rhi/d3d12/device/get-factory.md @@ -0,0 +1,19 @@ +# D3D12Device::GetFactory + +```cpp +IDXGIFactory4* GetFactory() const +``` + +获取底层 DXGI 工厂指针。 + +**返回:** DXGI 工厂指针 + +**示例:** + +```cpp +IDXGIFactory4* factory = d3d12Device->GetFactory(); +``` + +## 相关文档 + +- [D3D12Device 总览](device.md) - 返回类总览 diff --git a/docs/api/rhi/d3d12/device/methods.md b/docs/api/rhi/d3d12/device/methods.md new file mode 100644 index 0000000..fd1ef2a --- /dev/null +++ b/docs/api/rhi/d3d12/device/methods.md @@ -0,0 +1,165 @@ +# D3D12Device 方法 + +## 继承方法 + +### Initialize + +```cpp +bool Initialize(const RHIDeviceDesc& desc) override; +``` + +初始化 D3D12 设备。 + +### Shutdown + +```cpp +void Shutdown() override; +``` + +关闭设备。 + +### CreateBuffer + +```cpp +RHIBuffer* CreateBuffer(const BufferDesc& desc) override; +``` + +创建 D3D12 缓冲区。 + +### CreateTexture + +```cpp +RHITexture* CreateTexture(const TextureDesc& desc) override; +``` + +创建 D3D12 纹理。 + +### CreateSwapChain + +```cpp +RHISwapChain* CreateSwapChain(const SwapChainDesc& desc) override; +``` + +创建 D3D12 交换链。 + +### CreateCommandList + +```cpp +RHICommandList* CreateCommandList(const CommandListDesc& desc) override; +``` + +创建 D3D12 命令列表。 + +### CreateCommandQueue + +```cpp +RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) override; +``` + +创建 D3D12 命令队列。 + +### CompileShader + +```cpp +RHIShader* CompileShader(const ShaderCompileDesc& desc) override; +``` + +编译 D3D12 着色器。 + +### CreatePipelineState + +```cpp +RHIPipelineState* CreatePipelineState(const PipelineStateDesc& desc) override; +``` + +创建 D3D12 管线状态对象。 + +### CreateFence + +```cpp +RHIFence* CreateFence(const FenceDesc& desc) override; +``` + +创建 D3D12 栅栏。 + +### CreateSampler + +```cpp +RHISampler* CreateSampler(const SamplerDesc& desc) override; +``` + +创建 D3D12 采样器。 + +### GetCapabilities + +```cpp +const RHICapabilities& GetCapabilities() const override; +``` + +获取设备能力。 + +### GetDeviceInfo + +```cpp +const RHIDeviceInfo& GetDeviceInfo() const override; +``` + +获取设备信息。 + +### GetNativeDevice + +```cpp +void* GetNativeDevice() override; +``` + +获取原生 D3D12 设备指针。 + +## D3D12 特有方法 + +### GetDevice + +```cpp +ID3D12Device* GetDevice() const; +``` + +获取 `ID3D12Device` 接口。 + +### GetFactory + +```cpp +IDXGIFactory4* GetFactory() const; +``` + +获取 `IDXGIFactory4` 接口。 + +### GetAdapterInfo + +```cpp +const AdapterInfo& GetAdapterInfo() const; +``` + +获取适配器信息。 + +### EnumerateAdapters + +```cpp +std::vector EnumerateAdapters(); +``` + +枚举所有适配器。 + +### GetDescriptorHandleIncrementSize + +```cpp +UINT GetDescriptorHandleIncrementSize(DescriptorHeapType type) const; +``` + +获取描述符句柄增量大小。 + +### CheckFeatureSupport + +```cpp +bool CheckFeatureSupport(D3D12_FEATURE feature, void* featureSupportData, uint32_t featureSupportDataSize); +``` + +检查功能支持。 diff --git a/docs/api/rhi/d3d12/enums/enums.md b/docs/api/rhi/d3d12/enums/enums.md new file mode 100644 index 0000000..b43015c --- /dev/null +++ b/docs/api/rhi/d3d12/enums/enums.md @@ -0,0 +1,37 @@ +# D3D12Enum + +**命名空间**: `XCEngine::RHI` + +**描述**: D3D12 枚举值转换函数集合,提供 RHI 抽象枚举到 D3D12 原生枚举的转换。**所有函数均为 inline 函数**。 + +## 转换函数列表 + +| 函数 | 描述 | +|------|------| +| `ToD3D12(FillMode)` | 填充模式转换 | +| `ToD3D12(CullMode)` | 剔除模式转换 | +| `ToD3D12(ComparisonFunc)` | 比较函数转换 | +| `ToD3D12(StencilOp)` | 模板操作转换 | +| `ToD3D12(BlendOp)` | 混合操作转换 | +| `ToD3D12(BlendFactor)` | 混合因子转换 | +| `ToD3D12(LogicOp)` | 逻辑操作转换 | +| `ToD3D12(FilterMode)` | 过滤器模式转换 | +| `ToD3D12(TextureAddressMode)` | 纹理寻址模式转换 | +| `ToD3D12(BorderColor)` | 边框颜色转换 | +| `ToD3D12(ShaderVisibility)` | Shader 可见性转换 | +| `ToD3D12(Format)` | 格式转换 | +| `ToDXGI(Format)` | DXGI 格式转换 | +| `ToD3D12(ResourceStates)` | 资源状态转换 | +| `ToD3D12(HeapType)` | 堆类型转换 | +| `ToD3D12(PrimitiveTopology)` | 图元拓扑类型转换 | +| `ToD3D12Topology` | 图元拓扑详细转换 | +| `ToD3D12(DescriptorHeapType)` | 描述符堆类型转换 | +| `ToD3D12(QueryType)` | 查询类型转换 | +| `ToD3D12(RootParameterType)` | 根参数类型转换 | +| `ToD3D12(TextureType)` | 纹理类型维度转换 | +| `ToD3D12(CommandQueueType)` | 命令列表类型转换 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) +- [D3D12Types](../../types/types.md) - 类型转换 diff --git a/docs/api/rhi/d3d12/fence/fence.md b/docs/api/rhi/d3d12/fence/fence.md new file mode 100644 index 0000000..7b75051 --- /dev/null +++ b/docs/api/rhi/d3d12/fence/fence.md @@ -0,0 +1,24 @@ +# D3D12Fence + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 栅栏同步对象的 D3D12 实现,继承自 `RHIFence`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化栅栏 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭栅栏 | +| [`Signal`](signal.md) | 信号栅栏 | +| [`Wait`](../../../threading/task-group/wait.md) | 等待栅栏 | +| [`GetCompletedValue`](get-completed-value.md) | 获取完成值 | +| [`IsSignaled`](is-signaled.md) | 检查是否已信号 | +| [`GetEventHandle`](get-event-handle.md) | 获取事件句柄 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | +| [`GetFence`](get-fence.md) | 获取 D3D12 栅栏 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) +- [RHIFence](../../fence/fence.md) - 抽象栅栏接口 diff --git a/docs/api/rhi/d3d12/fence/get-completed-value.md b/docs/api/rhi/d3d12/fence/get-completed-value.md new file mode 100644 index 0000000..bbead1a --- /dev/null +++ b/docs/api/rhi/d3d12/fence/get-completed-value.md @@ -0,0 +1,34 @@ +# D3D12Fence::GetCompletedValue + +## 函数签名 + +```cpp +uint64_t GetCompletedValue() const override +``` + +## 中文描述 + +获取 GPU 已完成的最新栅栏值。 + +## 返回值 + +`uint64_t` - 已完成的栅栏值 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +uint64_t completedValue = d3d12Fence->GetCompletedValue(); +if (completedValue >= fenceValue) { + // 指定的栅栏值已完成 +} +``` + +## 相关文档 + +- [D3D12Fence](fence.md) - 类总览 +- [D3D12Fence::Signal](signal.md) - 信号栅栏 +- [D3D12Fence::IsSignaled](is-signaled.md) - 检查是否已信号 diff --git a/docs/api/rhi/d3d12/fence/get-event-handle.md b/docs/api/rhi/d3d12/fence/get-event-handle.md new file mode 100644 index 0000000..cc88943 --- /dev/null +++ b/docs/api/rhi/d3d12/fence/get-event-handle.md @@ -0,0 +1,31 @@ +# D3D12Fence::GetEventHandle + +## 函数签名 + +```cpp +void* GetEventHandle() +``` + +## 中文描述 + +获取用于 CPU 等待的 event 句柄。用于 `WaitForSingleObject` 等 API 进行阻塞等待。 + +## 返回值 + +`void*` - Win32 event 句柄 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +HANDLE eventHandle = static_cast(d3d12Fence->GetEventHandle()); +WaitForSingleObject(eventHandle, INFINITE); +``` + +## 相关文档 + +- [D3D12Fence](fence.md) - 类总览 +- [D3D12Fence::Wait](../../../threading/task-group/wait.md) - 等待栅栏 diff --git a/docs/api/rhi/d3d12/fence/get-fence.md b/docs/api/rhi/d3d12/fence/get-fence.md new file mode 100644 index 0000000..4084d48 --- /dev/null +++ b/docs/api/rhi/d3d12/fence/get-fence.md @@ -0,0 +1,30 @@ +# D3D12Fence::GetFence + +## 函数签名 + +```cpp +ID3D12Fence* GetFence() const +``` + +## 中文描述 + +获取底层 `ID3D12Fence` 接口指针。 + +## 返回值 + +`ID3D12Fence*` - D3D12 栅栏接口指针 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +ID3D12Fence* fence = d3d12Fence->GetFence(); +``` + +## 相关文档 + +- [D3D12Fence](fence.md) - 类总览 +- [D3D12Fence::GetNativeHandle](../../buffer/get-native-handle.md) - 获取原生句柄 diff --git a/docs/api/rhi/d3d12/fence/is-signaled.md b/docs/api/rhi/d3d12/fence/is-signaled.md new file mode 100644 index 0000000..b6c622d --- /dev/null +++ b/docs/api/rhi/d3d12/fence/is-signaled.md @@ -0,0 +1,33 @@ +# D3D12Fence::IsSignaled + +## 函数签名 + +```cpp +bool IsSignaled() const override +``` + +## 中文描述 + +检查当前栅栏值是否已达到 signal 值。 + +## 返回值 + +`bool` - 如果已完成则返回 `true`,否则返回 `false` + +## 复杂度 + +O(1) + +## 示例 + +```cpp +if (d3d12Fence->IsSignaled()) { + // 栅栏已完成,可以继续执行 +} +``` + +## 相关文档 + +- [D3D12Fence](fence.md) - 类总览 +- [D3D12Fence::GetCompletedValue](get-completed-value.md) - 获取完成值 +- [D3D12Fence::Wait](../../../threading/task-group/wait.md) - 等待栅栏 diff --git a/docs/api/rhi/d3d12/fence/signal.md b/docs/api/rhi/d3d12/fence/signal.md new file mode 100644 index 0000000..6344e27 --- /dev/null +++ b/docs/api/rhi/d3d12/fence/signal.md @@ -0,0 +1,46 @@ +# D3D12Fence::Signal + +## 函数签名 + +```cpp +void Signal() override +``` + +## 中文描述 + +将栅栏值设置为 GPU 当前 signaled 值,通常用于标记命令队列执行完成。 + +## 重载 + +| 版本 | 签名 | +|------|------| +| 无参数 | `void Signal()` | +| 带值 | `void Signal(uint64_t value)` | + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `value` | `uint64_t` | 要设置的栅栏值(仅带参数版本) | + +## 返回值 + +无 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +d3d12Fence->Signal(); +// 或指定值 +d3d12Fence->Signal(1); +``` + +## 相关文档 + +- [D3D12Fence](fence.md) - 类总览 +- [D3D12Fence::Wait](../../../threading/task-group/wait.md) - 等待栅栏 +- [D3D12Fence::GetCompletedValue](get-completed-value.md) - 获取完成值 diff --git a/docs/api/rhi/d3d12/pipeline-state/create-desc.md b/docs/api/rhi/d3d12/pipeline-state/create-desc.md new file mode 100644 index 0000000..b2e5060 --- /dev/null +++ b/docs/api/rhi/d3d12/pipeline-state/create-desc.md @@ -0,0 +1,53 @@ +# D3D12PipelineState::CreateDesc + +## 函数签名 + +```cpp +static D3D12_GRAPHICS_PIPELINE_STATE_DESC CreateDesc( + ID3D12RootSignature* rootSignature, + const D3D12_SHADER_BYTECODE& vs, + const D3D12_SHADER_BYTECODE& ps, + const D3D12_SHADER_BYTECODE& gs, + uint32_t inputElementCount, + const D3D12_INPUT_ELEMENT_DESC* inputElements) +``` + +## 中文描述 + +创建图形管线状态描述符,包含着色器和输入布局信息。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `rootSignature` | `ID3D12RootSignature*` | 根签名指针 | +| `vs` | `D3D12_SHADER_BYTECODE` | 顶点着色器字节码 | +| `ps` | `D3D12_SHADER_BYTECODE` | 像素着色器字节码 | +| `gs` | `D3D12_SHADER_BYTECODE` | 几何着色器字节码 | +| `inputElementCount` | `uint32_t` | 输入元素数量 | +| `inputElements` | `D3D12_INPUT_ELEMENT_DESC*` | 输入元素描述数组 | + +## 返回值 + +`D3D12_GRAPHICS_PIPELINE_STATE_DESC` - 管线状态描述符 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = D3D12PipelineState::CreateDesc( + rootSignature->GetRootSignature(), + vsBytecode, + psBytecode, + gsBytecode, + inputElementCount, + inputElements); +``` + +## 相关文档 + +- [D3D12PipelineState](pipeline-state.md) - 类总览 +- [D3D12PipelineState::CreateInputElement](create-input-element.md) - 创建输入元素 diff --git a/docs/api/rhi/d3d12/pipeline-state/create-input-element.md b/docs/api/rhi/d3d12/pipeline-state/create-input-element.md new file mode 100644 index 0000000..dd3999d --- /dev/null +++ b/docs/api/rhi/d3d12/pipeline-state/create-input-element.md @@ -0,0 +1,54 @@ +# D3D12PipelineState::CreateInputElement + +## 函数签名 + +```cpp +static D3D12_INPUT_ELEMENT_DESC CreateInputElement( + const char* semanticName, + uint32_t semanticIndex, + Format format, + uint32_t inputSlot, + uint32_t alignedByteOffset) + +static D3D12_INPUT_ELEMENT_DESC CreateInputElement( + const char* semanticName, + uint32_t semanticIndex, + Format format, + uint32_t inputSlot) +``` + +## 中文描述 + +创建输入元素描述符,用于定义顶点缓冲区的数据布局。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `semanticName` | `const char*` | 语义名称(如 "POSITION", "TEXCOORD") | +| `semanticIndex` | `uint32_t` | 语义索引 | +| `format` | `Format` | 数据格式 | +| `inputSlot` | `uint32_t` | 输入槽位 | +| `alignedByteOffset` | `uint32_t` | 对齐字节偏移(仅第一个重载) | + +## 返回值 + +`D3D12_INPUT_ELEMENT_DESC` - 输入元素描述符 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_INPUT_ELEMENT_DESC elements[] = { + D3D12PipelineState::CreateInputElement("POSITION", 0, Format::R32G32B32_FLOAT, 0, 0), + D3D12PipelineState::CreateInputElement("TEXCOORD", 0, Format::R32G32_FLOAT, 0, 12) +}; +``` + +## 相关文档 + +- [D3D12PipelineState](pipeline-state.md) - 类总览 +- [D3D12PipelineState::CreateDesc](create-desc.md) - 创建管线描述符 diff --git a/docs/api/rhi/d3d12/pipeline-state/get-pipeline-state.md b/docs/api/rhi/d3d12/pipeline-state/get-pipeline-state.md new file mode 100644 index 0000000..c087ec7 --- /dev/null +++ b/docs/api/rhi/d3d12/pipeline-state/get-pipeline-state.md @@ -0,0 +1,29 @@ +# D3D12PipelineState::GetPipelineState + +## 函数签名 + +```cpp +ID3D12PipelineState* GetPipelineState() const +``` + +## 中文描述 + +获取底层 `ID3D12PipelineState` 接口指针。 + +## 返回值 + +`ID3D12PipelineState*` - D3D12 管线状态对象接口指针 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +ID3D12PipelineState* pso = pipelineState->GetPipelineState(); +``` + +## 相关文档 + +- [D3D12PipelineState](pipeline-state.md) - 类总览 diff --git a/docs/api/rhi/d3d12/pipeline-state/pipeline-state.md b/docs/api/rhi/d3d12/pipeline-state/pipeline-state.md new file mode 100644 index 0000000..e2e2442 --- /dev/null +++ b/docs/api/rhi/d3d12/pipeline-state/pipeline-state.md @@ -0,0 +1,24 @@ +# D3D12PipelineState + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 管线状态对象的 D3D12 实现,继承自 `RHIPipelineState`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化管线状态 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭管线状态 | +| [`GetPipelineState`](get-pipeline-state.md) | 获取 D3D12 管线状态对象 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | +| [`GetType`](../../command-queue/get-type.md) | 获取管线类型 | +| [`Bind`](../../shader/bind.md) | 绑定管线状态 | +| [`Unbind`](../../shader/unbind.md) | 解绑管线状态 | +| [`CreateDesc`](create-desc.md) | 创建管线状态描述符(静态) | +| [`CreateInputElement`](create-input-element.md) | 创建输入元素描述符(静态) | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) +- [RHIPipelineState](../../pipeline-state/pipeline-state.md) - 抽象管线状态接口 diff --git a/docs/api/rhi/d3d12/query-heap/get-count.md b/docs/api/rhi/d3d12/query-heap/get-count.md new file mode 100644 index 0000000..c730e8b --- /dev/null +++ b/docs/api/rhi/d3d12/query-heap/get-count.md @@ -0,0 +1,29 @@ +# D3D12QueryHeap::GetCount + +## 函数签名 + +```cpp +uint32_t GetCount() const +``` + +## 中文描述 + +获取查询堆中的查询数量。 + +## 返回值 + +`uint32_t` - 查询数量 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +uint32_t count = d3d12QueryHeap->GetCount(); +``` + +## 相关文档 + +- [D3D12QueryHeap](query-heap.md) - 类总览 diff --git a/docs/api/rhi/d3d12/query-heap/get-query-heap.md b/docs/api/rhi/d3d12/query-heap/get-query-heap.md new file mode 100644 index 0000000..3e37c4e --- /dev/null +++ b/docs/api/rhi/d3d12/query-heap/get-query-heap.md @@ -0,0 +1,29 @@ +# D3D12QueryHeap::GetQueryHeap + +## 函数签名 + +```cpp +ID3D12QueryHeap* GetQueryHeap() const +``` + +## 中文描述 + +获取底层 `ID3D12QueryHeap` 接口指针。 + +## 返回值 + +`ID3D12QueryHeap*` - D3D12 查询堆接口指针 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +ID3D12QueryHeap* queryHeap = d3d12QueryHeap->GetQueryHeap(); +``` + +## 相关文档 + +- [D3D12QueryHeap](query-heap.md) - 类总览 diff --git a/docs/api/rhi/d3d12/query-heap/query-heap.md b/docs/api/rhi/d3d12/query-heap/query-heap.md new file mode 100644 index 0000000..06062b6 --- /dev/null +++ b/docs/api/rhi/d3d12/query-heap/query-heap.md @@ -0,0 +1,20 @@ +# D3D12QueryHeap + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 查询堆的 D3D12 实现。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化查询堆 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭查询堆 | +| [`GetQueryHeap`](get-query-heap.md) | 获取 D3D12 查询堆 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | +| [`GetType`](../../command-queue/get-type.md) | 获取查询类型 | +| [`GetCount`](get-count.md) | 获取查询数量 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) diff --git a/docs/api/rhi/d3d12/render-target-view/create-desc.md b/docs/api/rhi/d3d12/render-target-view/create-desc.md new file mode 100644 index 0000000..fc0675c --- /dev/null +++ b/docs/api/rhi/d3d12/render-target-view/create-desc.md @@ -0,0 +1,36 @@ +# D3D12RenderTargetView::CreateDesc + +## 函数签名 + +```cpp +static D3D12_RENDER_TARGET_VIEW_DESC CreateDesc(Format format, D3D12_RTV_DIMENSION dimension = D3D12_RTV_DIMENSION_TEXTURE2D) +``` + +## 中文描述 + +创建渲染目标视图描述符。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `format` | `Format` | 资源格式 | +| `dimension` | `D3D12_RTV_DIMENSION` | 视图维度(默认 TEXTURE2D) | + +## 返回值 + +`D3D12_RENDER_TARGET_VIEW_DESC` - 渲染目标视图描述符 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_RENDER_TARGET_VIEW_DESC desc = D3D12RenderTargetView::CreateDesc(Format::R8G8B8A8_UNorm); +``` + +## 相关文档 + +- [D3D12RenderTargetView](render-target-view.md) - 类总览 diff --git a/docs/api/rhi/d3d12/render-target-view/get-cpu-descriptor-handle.md b/docs/api/rhi/d3d12/render-target-view/get-cpu-descriptor-handle.md new file mode 100644 index 0000000..b68c7f5 --- /dev/null +++ b/docs/api/rhi/d3d12/render-target-view/get-cpu-descriptor-handle.md @@ -0,0 +1,29 @@ +# D3D12RenderTargetView::GetCPUDescriptorHandle + +## 函数签名 + +```cpp +D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() const +``` + +## 中文描述 + +获取渲染目标视图的 CPU 描述符句柄。 + +## 返回值 + +`D3D12_CPU_DESCRIPTOR_HANDLE` - CPU 描述符句柄 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_CPU_DESCRIPTOR_HANDLE handle = rtv->GetCPUDescriptorHandle(); +``` + +## 相关文档 + +- [D3D12RenderTargetView](render-target-view.md) - 类总览 diff --git a/docs/api/rhi/d3d12/render-target-view/initialize-at.md b/docs/api/rhi/d3d12/render-target-view/initialize-at.md new file mode 100644 index 0000000..7631860 --- /dev/null +++ b/docs/api/rhi/d3d12/render-target-view/initialize-at.md @@ -0,0 +1,40 @@ +# D3D12RenderTargetView::InitializeAt + +## 函数签名 + +```cpp +void InitializeAt(ID3D12Device* device, ID3D12Resource* resource, D3D12_CPU_DESCRIPTOR_HANDLE handle, const D3D12_RENDER_TARGET_VIEW_DESC* desc = nullptr) +``` + +## 中文描述 + +在指定描述符句柄位置初始化渲染目标视图,用于外部描述符堆管理场景。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `device` | `ID3D12Device*` | D3D12 设备指针 | +| `resource` | `ID3D12Resource*` | 资源指针 | +| `handle` | `D3D12_CPU_DESCRIPTOR_HANDLE` | 预分配的描述符句柄 | +| `desc` | `D3D12_RENDER_TARGET_VIEW_DESC*` | 视图描述符(可选) | + +## 返回值 + +无 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_CPU_DESCRIPTOR_HANDLE handle = descriptorHeap->GetCPUDescriptorHandleForHeapStart(); +rtv->InitializeAt(device, resource, handle); +``` + +## 相关文档 + +- [D3D12RenderTargetView](render-target-view.md) - 类总览 +- [D3D12RenderTargetView::Initialize](../../../threading/task-system/initialize.md) - 标准初始化 diff --git a/docs/api/rhi/d3d12/render-target-view/render-target-view.md b/docs/api/rhi/d3d12/render-target-view/render-target-view.md new file mode 100644 index 0000000..16e7ac9 --- /dev/null +++ b/docs/api/rhi/d3d12/render-target-view/render-target-view.md @@ -0,0 +1,19 @@ +# D3D12RenderTargetView + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 渲染目标视图的 D3D12 实现。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化渲染目标视图 | +| [`InitializeAt`](initialize-at.md) | 在指定位置初始化 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭渲染目标视图 | +| [`GetCPUDescriptorHandle`](get-cpu-descriptor-handle.md) | 获取 CPU 描述符句柄 | +| [`CreateDesc`](create-desc.md) | 创建描述符(静态) | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) diff --git a/docs/api/rhi/d3d12/root-signature/create-32bit-constants.md b/docs/api/rhi/d3d12/root-signature/create-32bit-constants.md new file mode 100644 index 0000000..d8961a7 --- /dev/null +++ b/docs/api/rhi/d3d12/root-signature/create-32bit-constants.md @@ -0,0 +1,38 @@ +# D3D12RootSignature::Create32BitConstants + +## 函数签名 + +```cpp +static D3D12_ROOT_PARAMETER Create32BitConstants(uint32_t shaderRegister, uint32_t num32BitValues, ShaderVisibility visibility = ShaderVisibility::All, uint32_t registerSpace = 0) +``` + +## 中文描述 + +创建 32 位常量根参数,用于上传小量常量数据。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `shaderRegister` | `uint32_t` | 着色器寄存器编号 | +| `num32BitValues` | `uint32_t` | 32 位值的数量 | +| `visibility` | `ShaderVisibility` | 可见性(默认 All) | +| `registerSpace` | `uint32_t` | 寄存器空间(默认 0) | + +## 返回值 + +`D3D12_ROOT_PARAMETER` - 根参数 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_ROOT_PARAMETER constantsParam = D3D12RootSignature::Create32BitConstants(0, 4); +``` + +## 相关文档 + +- [D3D12RootSignature](root-signature.md) - 类总览 diff --git a/docs/api/rhi/d3d12/root-signature/create-cbv.md b/docs/api/rhi/d3d12/root-signature/create-cbv.md new file mode 100644 index 0000000..b002c37 --- /dev/null +++ b/docs/api/rhi/d3d12/root-signature/create-cbv.md @@ -0,0 +1,39 @@ +# D3D12RootSignature::CreateCBV + +## 函数签名 + +```cpp +static D3D12_ROOT_PARAMETER CreateCBV(uint32_t shaderRegister, ShaderVisibility visibility = ShaderVisibility::All, uint32_t registerSpace = 0) +``` + +## 中文描述 + +创建常量缓冲区视图(CBV)根参数。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `shaderRegister` | `uint32_t` | 着色器寄存器编号 | +| `visibility` | `ShaderVisibility` | 可见性(默认 All) | +| `registerSpace` | `uint32_t` | 寄存器空间(默认 0) | + +## 返回值 + +`D3D12_ROOT_PARAMETER` - 根参数 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_ROOT_PARAMETER cbvParam = D3D12RootSignature::CreateCBV(0); +``` + +## 相关文档 + +- [D3D12RootSignature](root-signature.md) - 类总览 +- [D3D12RootSignature::CreateSRV](create-srv.md) - 创建 SRV 根参数 +- [D3D12RootSignature::CreateUAV](create-uav.md) - 创建 UAV 根参数 diff --git a/docs/api/rhi/d3d12/root-signature/create-desc.md b/docs/api/rhi/d3d12/root-signature/create-desc.md new file mode 100644 index 0000000..96eaabc --- /dev/null +++ b/docs/api/rhi/d3d12/root-signature/create-desc.md @@ -0,0 +1,48 @@ +# D3D12RootSignature::CreateDesc + +## 函数签名 + +```cpp +static D3D12_ROOT_SIGNATURE_DESC CreateDesc( + D3D12_ROOT_PARAMETER* parameters, + uint32_t parameterCount, + D3D12_STATIC_SAMPLER_DESC* samplers = nullptr, + uint32_t samplerCount = 0, + D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT) +``` + +## 中文描述 + +创建根签名描述符。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `parameters` | `D3D12_ROOT_PARAMETER*` | 根参数数组 | +| `parameterCount` | `uint32_t` | 根参数数量 | +| `samplers` | `D3D12_STATIC_SAMPLER_DESC*` | 静态采样器数组(可选) | +| `samplerCount` | `uint32_t` | 静态采样器数量 | +| `flags` | `D3D12_ROOT_SIGNATURE_FLAGS` | 根签名标志 | + +## 返回值 + +`D3D12_ROOT_SIGNATURE_DESC` - 根签名描述符 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_ROOT_SIGNATURE_DESC desc = D3D12RootSignature::CreateDesc( + parameters.data(), + parameters.size(), + samplers.data(), + samplers.size()); +``` + +## 相关文档 + +- [D3D12RootSignature](root-signature.md) - 类总览 diff --git a/docs/api/rhi/d3d12/root-signature/create-descriptor-range.md b/docs/api/rhi/d3d12/root-signature/create-descriptor-range.md new file mode 100644 index 0000000..5853b14 --- /dev/null +++ b/docs/api/rhi/d3d12/root-signature/create-descriptor-range.md @@ -0,0 +1,39 @@ +# D3D12RootSignature::CreateDescriptorRange + +## 函数签名 + +```cpp +static D3D12_DESCRIPTOR_RANGE CreateDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE type, uint32_t baseShaderRegister, uint32_t numDescriptors, uint32_t registerSpace = 0) +``` + +## 中文描述 + +创建描述符范围。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `type` | `D3D12_DESCRIPTOR_RANGE_TYPE` | 描述符范围类型 | +| `baseShaderRegister` | `uint32_t` | 基础着色器寄存器 | +| `numDescriptors` | `uint32_t` | 描述符数量 | +| `registerSpace` | `uint32_t` | 寄存器空间(默认 0) | + +## 返回值 + +`D3D12_DESCRIPTOR_RANGE` - 描述符范围 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_DESCRIPTOR_RANGE range = D3D12RootSignature::CreateDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 1); +``` + +## 相关文档 + +- [D3D12RootSignature](root-signature.md) - 类总览 +- [D3D12RootSignature::CreateDescriptorTable](create-descriptor-table.md) - 创建描述符表 diff --git a/docs/api/rhi/d3d12/root-signature/create-descriptor-table.md b/docs/api/rhi/d3d12/root-signature/create-descriptor-table.md new file mode 100644 index 0000000..35433d0 --- /dev/null +++ b/docs/api/rhi/d3d12/root-signature/create-descriptor-table.md @@ -0,0 +1,40 @@ +# D3D12RootSignature::CreateDescriptorTable + +## 函数签名 + +```cpp +static D3D12_ROOT_PARAMETER CreateDescriptorTable(uint32_t numRanges, const D3D12_DESCRIPTOR_RANGE* ranges, ShaderVisibility visibility = ShaderVisibility::All) +``` + +## 中文描述 + +创建描述符表根参数。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `numRanges` | `uint32_t` | 描述符范围数量 | +| `ranges` | `D3D12_DESCRIPTOR_RANGE*` | 描述符范围数组 | +| `visibility` | `ShaderVisibility` | 可见性(默认 All) | + +## 返回值 + +`D3D12_ROOT_PARAMETER` - 根参数 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_DESCRIPTOR_RANGE ranges[1]; +ranges[0] = D3D12RootSignature::CreateDescriptorRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 1); +D3D12_ROOT_PARAMETER descTable = D3D12RootSignature::CreateDescriptorTable(1, ranges); +``` + +## 相关文档 + +- [D3D12RootSignature](root-signature.md) - 类总览 +- [D3D12RootSignature::CreateDescriptorRange](create-descriptor-range.md) - 创建描述符范围 diff --git a/docs/api/rhi/d3d12/root-signature/create-sampler-desc.md b/docs/api/rhi/d3d12/root-signature/create-sampler-desc.md new file mode 100644 index 0000000..bff4b57 --- /dev/null +++ b/docs/api/rhi/d3d12/root-signature/create-sampler-desc.md @@ -0,0 +1,38 @@ +# D3D12RootSignature::CreateSamplerDesc + +## 函数签名 + +```cpp +static D3D12_SAMPLER_DESC CreateSamplerDesc(FilterMode filter, TextureAddressMode address, float maxLOD = D3D12_FLOAT32_MAX) +``` + +## 中文描述 + +创建采样器描述符。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `filter` | `FilterMode` | 过滤模式 | +| `address` | `TextureAddressMode` | 寻址模式 | +| `maxLOD` | `float` | 最大 LOD(默认无限) | + +## 返回值 + +`D3D12_SAMPLER_DESC` - 采样器描述符 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_SAMPLER_DESC desc = D3D12RootSignature::CreateSamplerDesc(FilterMode::Anisotropic, TextureAddressMode::Wrap); +``` + +## 相关文档 + +- [D3D12RootSignature](root-signature.md) - 类总览 +- [D3D12RootSignature::CreateStaticSampler](create-static-sampler.md) - 创建静态采样器 diff --git a/docs/api/rhi/d3d12/root-signature/create-srv.md b/docs/api/rhi/d3d12/root-signature/create-srv.md new file mode 100644 index 0000000..04a885e --- /dev/null +++ b/docs/api/rhi/d3d12/root-signature/create-srv.md @@ -0,0 +1,39 @@ +# D3D12RootSignature::CreateSRV + +## 函数签名 + +```cpp +static D3D12_ROOT_PARAMETER CreateSRV(uint32_t shaderRegister, ShaderVisibility visibility = ShaderVisibility::All, uint32_t registerSpace = 0) +``` + +## 中文描述 + +创建着色器资源视图(SRV)根参数。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `shaderRegister` | `uint32_t` | 着色器寄存器编号 | +| `visibility` | `ShaderVisibility` | 可见性(默认 All) | +| `registerSpace` | `uint32_t` | 寄存器空间(默认 0) | + +## 返回值 + +`D3D12_ROOT_PARAMETER` - 根参数 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_ROOT_PARAMETER srvParam = D3D12RootSignature::CreateSRV(0); +``` + +## 相关文档 + +- [D3D12RootSignature](root-signature.md) - 类总览 +- [D3D12RootSignature::CreateCBV](create-cbv.md) - 创建 CBV 根参数 +- [D3D12RootSignature::CreateUAV](create-uav.md) - 创建 UAV 根参数 diff --git a/docs/api/rhi/d3d12/root-signature/create-static-sampler.md b/docs/api/rhi/d3d12/root-signature/create-static-sampler.md new file mode 100644 index 0000000..3b2f15e --- /dev/null +++ b/docs/api/rhi/d3d12/root-signature/create-static-sampler.md @@ -0,0 +1,39 @@ +# D3D12RootSignature::CreateStaticSampler + +## 函数签名 + +```cpp +static D3D12_STATIC_SAMPLER_DESC CreateStaticSampler(uint32_t shaderRegister, const D3D12_SAMPLER_DESC& desc, ShaderVisibility visibility = ShaderVisibility::Pixel) +``` + +## 中文描述 + +创建静态采样器描述符,静态采样器绑定到根签名中无需描述符堆。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `shaderRegister` | `uint32_t` | 着色器寄存器编号 | +| `desc` | `D3D12_SAMPLER_DESC` | 采样器描述符 | +| `visibility` | `ShaderVisibility` | 可见性(默认 Pixel) | + +## 返回值 + +`D3D12_STATIC_SAMPLER_DESC` - 静态采样器描述符 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_SAMPLER_DESC samplerDesc = D3D12RootSignature::CreateSamplerDesc(FilterMode::Anisotropic, TextureAddressMode::Wrap); +D3D12_STATIC_SAMPLER_DESC staticSampler = D3D12RootSignature::CreateStaticSampler(0, samplerDesc); +``` + +## 相关文档 + +- [D3D12RootSignature](root-signature.md) - 类总览 +- [D3D12RootSignature::CreateSamplerDesc](create-sampler-desc.md) - 创建采样器描述符 diff --git a/docs/api/rhi/d3d12/root-signature/create-uav.md b/docs/api/rhi/d3d12/root-signature/create-uav.md new file mode 100644 index 0000000..3404f2a --- /dev/null +++ b/docs/api/rhi/d3d12/root-signature/create-uav.md @@ -0,0 +1,39 @@ +# D3D12RootSignature::CreateUAV + +## 函数签名 + +```cpp +static D3D12_ROOT_PARAMETER CreateUAV(uint32_t shaderRegister, ShaderVisibility visibility = ShaderVisibility::All, uint32_t registerSpace = 0) +``` + +## 中文描述 + +创建无序访问视图(UAV)根参数。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `shaderRegister` | `uint32_t` | 着色器寄存器编号 | +| `visibility` | `ShaderVisibility` | 可见性(默认 All) | +| `registerSpace` | `uint32_t` | 寄存器空间(默认 0) | + +## 返回值 + +`D3D12_ROOT_PARAMETER` - 根参数 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_ROOT_PARAMETER uavParam = D3D12RootSignature::CreateUAV(0); +``` + +## 相关文档 + +- [D3D12RootSignature](root-signature.md) - 类总览 +- [D3D12RootSignature::CreateCBV](create-cbv.md) - 创建 CBV 根参数 +- [D3D12RootSignature::CreateSRV](create-srv.md) - 创建 SRV 根参数 diff --git a/docs/api/rhi/d3d12/root-signature/get-parameter-count.md b/docs/api/rhi/d3d12/root-signature/get-parameter-count.md new file mode 100644 index 0000000..fa075eb --- /dev/null +++ b/docs/api/rhi/d3d12/root-signature/get-parameter-count.md @@ -0,0 +1,29 @@ +# D3D12RootSignature::GetParameterCount + +## 函数签名 + +```cpp +uint32_t GetParameterCount() const +``` + +## 中文描述 + +获取根签名中根参数的数量。 + +## 返回值 + +`uint32_t` - 根参数数量 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +uint32_t count = rootSignature->GetParameterCount(); +``` + +## 相关文档 + +- [D3D12RootSignature](root-signature.md) - 类总览 diff --git a/docs/api/rhi/d3d12/root-signature/get-root-signature.md b/docs/api/rhi/d3d12/root-signature/get-root-signature.md new file mode 100644 index 0000000..2273625 --- /dev/null +++ b/docs/api/rhi/d3d12/root-signature/get-root-signature.md @@ -0,0 +1,29 @@ +# D3D12RootSignature::GetRootSignature + +## 函数签名 + +```cpp +ID3D12RootSignature* GetRootSignature() const +``` + +## 中文描述 + +获取底层 `ID3D12RootSignature` 接口指针。 + +## 返回值 + +`ID3D12RootSignature*` - D3D12 根签名接口指针 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +ID3D12RootSignature* rs = rootSignature->GetRootSignature(); +``` + +## 相关文档 + +- [D3D12RootSignature](root-signature.md) - 类总览 diff --git a/docs/api/rhi/d3d12/root-signature/root-signature.md b/docs/api/rhi/d3d12/root-signature/root-signature.md new file mode 100644 index 0000000..ec578f6 --- /dev/null +++ b/docs/api/rhi/d3d12/root-signature/root-signature.md @@ -0,0 +1,28 @@ +# D3D12RootSignature + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 根签名的 D3D12 实现。**不继承 RHI 抽象接口**,是 D3D12 特有的封装类。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化根签名 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭根签名 | +| [`GetRootSignature`](get-root-signature.md) | 获取 D3D12 根签名 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | +| [`GetParameterCount`](get-parameter-count.md) | 获取参数数量 | +| [`CreateDesc`](create-desc.md) | 创建根签名描述符(静态) | +| [`CreateCBV`](create-cbv.md) | 创建常量缓冲区视图(静态) | +| [`CreateSRV`](create-srv.md) | 创建着色器资源视图(静态) | +| [`CreateUAV`](create-uav.md) | 创建无序访问视图(静态) | +| [`Create32BitConstants`](create-32bit-constants.md) | 创建 32 位常量(静态) | +| [`CreateDescriptorTable`](create-descriptor-table.md) | 创建描述符表(静态) | +| [`CreateStaticSampler`](create-static-sampler.md) | 创建静态采样器(静态) | +| [`CreateSamplerDesc`](create-sampler-desc.md) | 创建采样器描述符(静态) | +| [`CreateDescriptorRange`](create-descriptor-range.md) | 创建描述符范围(静态) | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) diff --git a/docs/api/rhi/d3d12/sampler/get-id.md b/docs/api/rhi/d3d12/sampler/get-id.md new file mode 100644 index 0000000..aa70e34 --- /dev/null +++ b/docs/api/rhi/d3d12/sampler/get-id.md @@ -0,0 +1,29 @@ +# D3D12Sampler::GetID + +## 函数签名 + +```cpp +unsigned int GetID() override +``` + +## 中文描述 + +获取采样器唯一标识符。 + +## 返回值 + +`unsigned int` - 采样器 ID + +## 复杂度 + +O(1) + +## 示例 + +```cpp +unsigned int id = sampler->GetID(); +``` + +## 相关文档 + +- [D3D12Sampler](sampler.md) - 类总览 diff --git a/docs/api/rhi/d3d12/sampler/sampler.md b/docs/api/rhi/d3d12/sampler/sampler.md new file mode 100644 index 0000000..fab87f1 --- /dev/null +++ b/docs/api/rhi/d3d12/sampler/sampler.md @@ -0,0 +1,22 @@ +# D3D12Sampler + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 采样器的 D3D12 实现,继承自 `RHISampler`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化采样器 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭采样器 | +| [`GetDesc`](../buffer/get-desc.md) | 获取采样器描述符 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | +| [`GetID`](get-id.md) | 获取采样器 ID | +| [`Bind`](../../shader/bind.md) | 绑定采样器 | +| [`Unbind`](../../shader/unbind.md) | 解绑采样器 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) +- [RHISampler](../../sampler/sampler.md) - 抽象采样器接口 diff --git a/docs/api/rhi/d3d12/screenshot/capture.md b/docs/api/rhi/d3d12/screenshot/capture.md new file mode 100644 index 0000000..2e52781 --- /dev/null +++ b/docs/api/rhi/d3d12/screenshot/capture.md @@ -0,0 +1,46 @@ +# D3D12Screenshot::Capture + +## 函数签名 + +```cpp +static bool Capture(ID3D12Device* device, + ID3D12CommandQueue* commandQueue, + ID3D12Resource* renderTarget, + const char* filename, + uint32_t width, + uint32_t height) +``` + +## 中文描述 + +从渲染目标捕获截图并保存为文件。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `device` | `ID3D12Device*` | D3D12 设备指针 | +| `commandQueue` | `ID3D12CommandQueue*` | 命令队列指针 | +| `renderTarget` | `ID3D12Resource*` | 渲染目标资源 | +| `filename` | `const char*` | 保存文件名 | +| `width` | `uint32_t` | 宽度 | +| `height` | `uint32_t` | 高度 | + +## 返回值 + +`bool` - 捕获是否成功 + +## 复杂度 + +O(n) - 取决于纹理大小 + +## 示例 + +```cpp +D3D12Screenshot::Capture(device, commandQueue, renderTarget, "screenshot.png", width, height); +``` + +## 相关文档 + +- [D3D12Screenshot](screenshot.md) - 类总览 +- [D3D12Screenshot::CopyToReadbackAndSave](copy-to-readback-and-save.md) - 复制到回读缓冲并保存 diff --git a/docs/api/rhi/d3d12/screenshot/copy-to-readback-and-save.md b/docs/api/rhi/d3d12/screenshot/copy-to-readback-and-save.md new file mode 100644 index 0000000..44f6ac4 --- /dev/null +++ b/docs/api/rhi/d3d12/screenshot/copy-to-readback-and-save.md @@ -0,0 +1,46 @@ +# D3D12Screenshot::CopyToReadbackAndSave + +## 函数签名 + +```cpp +static bool CopyToReadbackAndSave(ID3D12Device* device, + ID3D12CommandQueue* commandQueue, + ID3D12Resource* renderTarget, + const char* filename, + uint32_t width, + uint32_t height) +``` + +## 中文描述 + +复制渲染目标到回读缓冲区并保存为图片文件。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `device` | `ID3D12Device*` | D3D12 设备指针 | +| `commandQueue` | `ID3D12CommandQueue*` | 命令队列指针 | +| `renderTarget` | `ID3D12Resource*` | 渲染目标资源 | +| `filename` | `const char*` | 保存文件名 | +| `width` | `uint32_t` | 宽度 | +| `height` | `uint32_t` | 高度 | + +## 返回值 + +`bool` - 操作是否成功 + +## 复杂度 + +O(n) - 取决于纹理大小 + +## 示例 + +```cpp +D3D12Screenshot::CopyToReadbackAndSave(device, commandQueue, renderTarget, "screenshot.png", width, height); +``` + +## 相关文档 + +- [D3D12Screenshot](screenshot.md) - 类总览 +- [D3D12Screenshot::Capture](capture.md) - 捕获截图 diff --git a/docs/api/rhi/d3d12/screenshot/screenshot.md b/docs/api/rhi/d3d12/screenshot/screenshot.md new file mode 100644 index 0000000..a8c2f48 --- /dev/null +++ b/docs/api/rhi/d3d12/screenshot/screenshot.md @@ -0,0 +1,16 @@ +# D3D12Screenshot + +**命名空间**: `XCEngine::RHI` + +**描述**: D3D12 截图工具类,提供屏幕截图捕获功能。**所有方法均为静态方法**。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Capture`](capture.md) | 捕获截图 | +| [`CopyToReadbackAndSave`](copy-to-readback-and-save.md) | 复制到回读缓冲并保存 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) diff --git a/docs/api/rhi/d3d12/shader-resource-view/create-desc.md b/docs/api/rhi/d3d12/shader-resource-view/create-desc.md new file mode 100644 index 0000000..019e427 --- /dev/null +++ b/docs/api/rhi/d3d12/shader-resource-view/create-desc.md @@ -0,0 +1,37 @@ +# D3D12ShaderResourceView::CreateDesc + +## 函数签名 + +```cpp +static D3D12_SHADER_RESOURCE_VIEW_DESC CreateDesc(Format format, D3D12_SRV_DIMENSION dimension = D3D12_SRV_DIMENSION_TEXTURE2D, uint32_t mipLevels = 1) +``` + +## 中文描述 + +创建着色器资源视图描述符。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `format` | `Format` | 资源格式 | +| `dimension` | `D3D12_SRV_DIMENSION` | 视图维度(默认 TEXTURE2D) | +| `mipLevels` | `uint32_t` | Mipmap 级别数量(默认 1) | + +## 返回值 + +`D3D12_SHADER_RESOURCE_VIEW_DESC` - 着色器资源视图描述符 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_SHADER_RESOURCE_VIEW_DESC desc = D3D12ShaderResourceView::CreateDesc(Format::R8G8B8A8_UNorm); +``` + +## 相关文档 + +- [D3D12ShaderResourceView](shader-resource-view.md) - 类总览 diff --git a/docs/api/rhi/d3d12/shader-resource-view/get-cpu-descriptor-handle.md b/docs/api/rhi/d3d12/shader-resource-view/get-cpu-descriptor-handle.md new file mode 100644 index 0000000..6b07bb5 --- /dev/null +++ b/docs/api/rhi/d3d12/shader-resource-view/get-cpu-descriptor-handle.md @@ -0,0 +1,29 @@ +# D3D12ShaderResourceView::GetCPUDescriptorHandle + +## 函数签名 + +```cpp +D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() const +``` + +## 中文描述 + +获取着色器资源视图的 CPU 描述符句柄。 + +## 返回值 + +`D3D12_CPU_DESCRIPTOR_HANDLE` - CPU 描述符句柄 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_CPU_DESCRIPTOR_HANDLE handle = srv->GetCPUDescriptorHandle(); +``` + +## 相关文档 + +- [D3D12ShaderResourceView](shader-resource-view.md) - 类总览 diff --git a/docs/api/rhi/d3d12/shader-resource-view/initialize-at.md b/docs/api/rhi/d3d12/shader-resource-view/initialize-at.md new file mode 100644 index 0000000..9746d5b --- /dev/null +++ b/docs/api/rhi/d3d12/shader-resource-view/initialize-at.md @@ -0,0 +1,39 @@ +# D3D12ShaderResourceView::InitializeAt + +## 函数签名 + +```cpp +void InitializeAt(ID3D12Device* device, ID3D12Resource* resource, D3D12_CPU_DESCRIPTOR_HANDLE handle, const D3D12_SHADER_RESOURCE_VIEW_DESC* desc = nullptr) +``` + +## 中文描述 + +在指定描述符句柄位置初始化着色器资源视图,用于外部描述符堆管理场景。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `device` | `ID3D12Device*` | D3D12 设备指针 | +| `resource` | `ID3D12Resource*` | 资源指针 | +| `handle` | `D3D12_CPU_DESCRIPTOR_HANDLE` | 预分配的描述符句柄 | +| `desc` | `D3D12_SHADER_RESOURCE_VIEW_DESC*` | 视图描述符(可选) | + +## 返回值 + +无 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_CPU_DESCRIPTOR_HANDLE handle = descriptorHeap->GetCPUDescriptorHandleForHeapStart(); +srv->InitializeAt(device, resource, handle); +``` + +## 相关文档 + +- [D3D12ShaderResourceView](shader-resource-view.md) - 类总览 diff --git a/docs/api/rhi/d3d12/shader-resource-view/shader-resource-view.md b/docs/api/rhi/d3d12/shader-resource-view/shader-resource-view.md new file mode 100644 index 0000000..fe40f87 --- /dev/null +++ b/docs/api/rhi/d3d12/shader-resource-view/shader-resource-view.md @@ -0,0 +1,19 @@ +# D3D12ShaderResourceView + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 着色器资源视图的 D3D12 实现。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化着色器资源视图 | +| [`InitializeAt`](initialize-at.md) | 在指定位置初始化 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭着色器资源视图 | +| [`GetCPUDescriptorHandle`](get-cpu-descriptor-handle.md) | 获取 CPU 描述符句柄 | +| [`CreateDesc`](create-desc.md) | 创建描述符(静态) | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) diff --git a/docs/api/rhi/d3d12/shader/get-bytecode-size.md b/docs/api/rhi/d3d12/shader/get-bytecode-size.md new file mode 100644 index 0000000..8c6b794 --- /dev/null +++ b/docs/api/rhi/d3d12/shader/get-bytecode-size.md @@ -0,0 +1,30 @@ +# D3D12Shader::GetBytecodeSize + +## 函数签名 + +```cpp +size_t GetBytecodeSize() const +``` + +## 中文描述 + +获取着色器字节码大小。 + +## 返回值 + +`size_t` - 字节码大小(字节) + +## 复杂度 + +O(1) + +## 示例 + +```cpp +size_t size = shader->GetBytecodeSize(); +``` + +## 相关文档 + +- [D3D12Shader](shader.md) - 类总览 +- [D3D12Shader::GetBytecode](get-bytecode.md) - 获取字节码数据 diff --git a/docs/api/rhi/d3d12/shader/get-bytecode.md b/docs/api/rhi/d3d12/shader/get-bytecode.md new file mode 100644 index 0000000..fe2cd8e --- /dev/null +++ b/docs/api/rhi/d3d12/shader/get-bytecode.md @@ -0,0 +1,30 @@ +# D3D12Shader::GetBytecode + +## 函数签名 + +```cpp +const void* GetBytecode() const +``` + +## 中文描述 + +获取着色器字节码数据指针。 + +## 返回值 + +`const void*` - 字节码数据指针 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +const void* bytecode = shader->GetBytecode(); +``` + +## 相关文档 + +- [D3D12Shader](shader.md) - 类总览 +- [D3D12Shader::GetBytecodeSize](get-bytecode-size.md) - 获取字节码大小 diff --git a/docs/api/rhi/d3d12/shader/get-d3d12-bytecode.md b/docs/api/rhi/d3d12/shader/get-d3d12-bytecode.md new file mode 100644 index 0000000..832a410 --- /dev/null +++ b/docs/api/rhi/d3d12/shader/get-d3d12-bytecode.md @@ -0,0 +1,29 @@ +# D3D12Shader::GetD3D12Bytecode + +## 函数签名 + +```cpp +const D3D12_SHADER_BYTECODE GetD3D12Bytecode() const +``` + +## 中文描述 + +获取 D3D12 着色器字节码结构。 + +## 返回值 + +`D3D12_SHADER_BYTECODE` - D3D12 着色器字节码结构 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_SHADER_BYTECODE bytecode = shader->GetD3D12Bytecode(); +``` + +## 相关文档 + +- [D3D12Shader](shader.md) - 类总览 diff --git a/docs/api/rhi/d3d12/shader/get-input-layout.md b/docs/api/rhi/d3d12/shader/get-input-layout.md new file mode 100644 index 0000000..94a33bb --- /dev/null +++ b/docs/api/rhi/d3d12/shader/get-input-layout.md @@ -0,0 +1,29 @@ +# D3D12Shader::GetInputLayout + +## 函数签名 + +```cpp +const InputLayoutDesc& GetInputLayout() const +``` + +## 中文描述 + +获取着色器输入布局描述。 + +## 返回值 + +`const InputLayoutDesc&` - 输入布局描述引用 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +const InputLayoutDesc& layout = shader->GetInputLayout(); +``` + +## 相关文档 + +- [D3D12Shader](shader.md) - 类总览 diff --git a/docs/api/rhi/d3d12/shader/set-uniforms.md b/docs/api/rhi/d3d12/shader/set-uniforms.md new file mode 100644 index 0000000..bf04a34 --- /dev/null +++ b/docs/api/rhi/d3d12/shader/set-uniforms.md @@ -0,0 +1,46 @@ +# D3D12Shader::SetUniforms + +## 函数签名 + +```cpp +void SetInt(const char* name, int value) override +void SetFloat(const char* name, float value) override +void SetVec3(const char* name, float x, float y, float z) override +void SetVec4(const char* name, float x, float y, float z, float w) override +void SetMat4(const char* name, const float* value) override +``` + +## 中文描述 + +设置着色器 uniform 变量。当前实现为空(stub)。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `name` | `const char*` | 变量名称 | +| `value` | 各种类型 | 变量值 | +| `x, y, z, w` | `float` | 向量分量 | +| `value` | `const float*` | 矩阵数据指针 | + +## 返回值 + +无 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +shader->SetInt("useLighting", 1); +shader->SetFloat("scale", 2.0f); +shader->SetVec3("lightPos", 1.0f, 2.0f, 3.0f); +shader->SetVec4("color", 1.0f, 0.0f, 0.0f, 1.0f); +shader->SetMat4("transform", matrixData); +``` + +## 相关文档 + +- [D3D12Shader](shader.md) - 类总览 diff --git a/docs/api/rhi/d3d12/shader/shader.md b/docs/api/rhi/d3d12/shader/shader.md new file mode 100644 index 0000000..0acf341 --- /dev/null +++ b/docs/api/rhi/d3d12/shader/shader.md @@ -0,0 +1,28 @@ +# D3D12Shader + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 着色器的 D3D12 实现,继承自 `RHIShader`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`CompileFromFile`](../../shader/compile-from-file.md) | 从文件编译着色器 | +| [`Compile`](../../shader/compile.md) | 从源码编译着色器 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭着色器 | +| [`GetD3D12Bytecode`](get-d3d12-bytecode.md) | 获取 D3D12 字节码 | +| [`GetBytecode`](get-bytecode.md) | 获取字节码 | +| [`GetBytecodeSize`](get-bytecode-size.md) | 获取字节码大小 | +| [`GetType`](../../command-queue/get-type.md) | 获取着色器类型 | +| [`GetInputLayout`](get-input-layout.md) | 获取输入布局 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | +| [`IsValid`](../../shader/is-valid.md) | 检查是否有效 | +| [`Bind`](../../shader/bind.md) | 绑定着色器 | +| [`Unbind`](../../shader/unbind.md) | 解绑着色器 | +| [`SetUniforms`](set-uniforms.md) | 设置 uniform 变量 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) +- [RHIShader](../../shader/shader.md) - 抽象着色器接口 diff --git a/docs/api/rhi/d3d12/swap-chain/get-back-buffer.md b/docs/api/rhi/d3d12/swap-chain/get-back-buffer.md new file mode 100644 index 0000000..9916688 --- /dev/null +++ b/docs/api/rhi/d3d12/swap-chain/get-back-buffer.md @@ -0,0 +1,35 @@ +# D3D12SwapChain::GetBackBuffer + +## 函数签名 + +```cpp +D3D12Texture* GetBackBuffer(uint32_t index) const +``` + +## 中文描述 + +获取指定索引的后台缓冲区。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `index` | `uint32_t` | 缓冲区索引 | + +## 返回值 + +`D3D12Texture*` - 后台缓冲区纹理指针 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12Texture* buffer = swapChain->GetBackBuffer(0); +``` + +## 相关文档 + +- [D3D12SwapChain](swap-chain.md) - 类总览 diff --git a/docs/api/rhi/d3d12/swap-chain/get-current-back-buffer-index.md b/docs/api/rhi/d3d12/swap-chain/get-current-back-buffer-index.md new file mode 100644 index 0000000..d8179a9 --- /dev/null +++ b/docs/api/rhi/d3d12/swap-chain/get-current-back-buffer-index.md @@ -0,0 +1,30 @@ +# D3D12SwapChain::GetCurrentBackBufferIndex + +## 函数签名 + +```cpp +uint32_t GetCurrentBackBufferIndex() const override +``` + +## 中文描述 + +获取当前后台缓冲区的索引。 + +## 返回值 + +`uint32_t` - 当前后台缓冲区索引 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +uint32_t index = swapChain->GetCurrentBackBufferIndex(); +``` + +## 相关文档 + +- [D3D12SwapChain](swap-chain.md) - 类总览 +- [D3D12SwapChain::GetCurrentBackBuffer](get-current-back-buffer.md) - 获取当前后台缓冲区 diff --git a/docs/api/rhi/d3d12/swap-chain/get-current-back-buffer.md b/docs/api/rhi/d3d12/swap-chain/get-current-back-buffer.md new file mode 100644 index 0000000..56b92e0 --- /dev/null +++ b/docs/api/rhi/d3d12/swap-chain/get-current-back-buffer.md @@ -0,0 +1,30 @@ +# D3D12SwapChain::GetCurrentBackBuffer + +## 函数签名 + +```cpp +RHITexture* GetCurrentBackBuffer() override +``` + +## 中文描述 + +获取当前后台缓冲区纹理。 + +## 返回值 + +`RHITexture*` - 当前后台缓冲区纹理指针 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +RHITexture* backBuffer = swapChain->GetCurrentBackBuffer(); +``` + +## 相关文档 + +- [D3D12SwapChain](swap-chain.md) - 类总览 +- [D3D12SwapChain::GetCurrentBackBufferIndex](get-current-back-buffer-index.md) - 获取当前缓冲区索引 diff --git a/docs/api/rhi/d3d12/swap-chain/get-swap-chain.md b/docs/api/rhi/d3d12/swap-chain/get-swap-chain.md new file mode 100644 index 0000000..83a6f81 --- /dev/null +++ b/docs/api/rhi/d3d12/swap-chain/get-swap-chain.md @@ -0,0 +1,29 @@ +# D3D12SwapChain::GetSwapChain + +## 函数签名 + +```cpp +IDXGISwapChain3* GetSwapChain() const +``` + +## 中文描述 + +获取底层 `IDXGISwapChain3` 接口指针。 + +## 返回值 + +`IDXGISwapChain3*` - DXGI 交换链接口指针 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +IDXGISwapChain3* swapChain = d3d12SwapChain->GetSwapChain(); +``` + +## 相关文档 + +- [D3D12SwapChain](swap-chain.md) - 类总览 diff --git a/docs/api/rhi/d3d12/swap-chain/initialize-from-swapchain.md b/docs/api/rhi/d3d12/swap-chain/initialize-from-swapchain.md new file mode 100644 index 0000000..3e9d111 --- /dev/null +++ b/docs/api/rhi/d3d12/swap-chain/initialize-from-swapchain.md @@ -0,0 +1,40 @@ +# D3D12SwapChain::Initialize + +## 函数签名 + +```cpp +bool Initialize(IDXGIFactory4* factory, ID3D12CommandQueue* commandQueue, HWND windowHandle, uint32_t width, uint32_t height, uint32_t bufferCount = 2) +``` + +## 中文描述 + +从工厂创建新的交换链。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `factory` | `IDXGIFactory4*` | DXGI 工厂指针 | +| `commandQueue` | `ID3D12CommandQueue*` | 命令队列指针 | +| `windowHandle` | `HWND` | 窗口句柄 | +| `width` | `uint32_t` | 宽度 | +| `height` | `uint32_t` | 高度 | +| `bufferCount` | `uint32_t` | 缓冲区数量(默认 2) | + +## 返回值 + +`bool` - 初始化是否成功 + +## 复杂度 + +O(n) - 取决于缓冲区数量和大小 + +## 示例 + +```cpp +swapChain->Initialize(factory, commandQueue, hwnd, 1920, 1080, 2); +``` + +## 相关文档 + +- [D3D12SwapChain](swap-chain.md) - 类总览 diff --git a/docs/api/rhi/d3d12/swap-chain/is-fullscreen.md b/docs/api/rhi/d3d12/swap-chain/is-fullscreen.md new file mode 100644 index 0000000..4fc3db1 --- /dev/null +++ b/docs/api/rhi/d3d12/swap-chain/is-fullscreen.md @@ -0,0 +1,32 @@ +# D3D12SwapChain::IsFullscreen + +## 函数签名 + +```cpp +bool IsFullscreen() const override +``` + +## 中文描述 + +检查交换链是否处于全屏模式。 + +## 返回值 + +`bool` - 如果全屏则返回 `true` + +## 复杂度 + +O(1) + +## 示例 + +```cpp +if (swapChain->IsFullscreen()) { + // 全屏模式 +} +``` + +## 相关文档 + +- [D3D12SwapChain](swap-chain.md) - 类总览 +- [D3D12SwapChain::SetFullscreen](set-fullscreen.md) - 设置全屏模式 diff --git a/docs/api/rhi/d3d12/swap-chain/poll-events.md b/docs/api/rhi/d3d12/swap-chain/poll-events.md new file mode 100644 index 0000000..230908b --- /dev/null +++ b/docs/api/rhi/d3d12/swap-chain/poll-events.md @@ -0,0 +1,29 @@ +# D3D12SwapChain::PollEvents + +## 函数签名 + +```cpp +void PollEvents() override +``` + +## 中文描述 + +处理窗口消息队列中的事件。 + +## 返回值 + +无 + +## 复杂度 + +O(n) - 取决于待处理事件数量 + +## 示例 + +```cpp +swapChain->PollEvents(); +``` + +## 相关文档 + +- [D3D12SwapChain](swap-chain.md) - 类总览 diff --git a/docs/api/rhi/d3d12/swap-chain/present.md b/docs/api/rhi/d3d12/swap-chain/present.md new file mode 100644 index 0000000..c5ebef6 --- /dev/null +++ b/docs/api/rhi/d3d12/swap-chain/present.md @@ -0,0 +1,36 @@ +# D3D12SwapChain::Present + +## 函数签名 + +```cpp +void Present(uint32_t syncInterval = 1, uint32_t flags = 0) override +``` + +## 中文描述 + +呈现后台缓冲区内容到屏幕。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `syncInterval` | `uint32_t` | 垂直同步间隔(默认 1) | +| `flags` | `uint32_t` | 呈现标志(默认 0) | + +## 返回值 + +无 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +swapChain->Present(1, 0); +``` + +## 相关文档 + +- [D3D12SwapChain](swap-chain.md) - 类总览 diff --git a/docs/api/rhi/d3d12/swap-chain/set-fullscreen.md b/docs/api/rhi/d3d12/swap-chain/set-fullscreen.md new file mode 100644 index 0000000..56e7d35 --- /dev/null +++ b/docs/api/rhi/d3d12/swap-chain/set-fullscreen.md @@ -0,0 +1,36 @@ +# D3D12SwapChain::SetFullscreen + +## 函数签名 + +```cpp +void SetFullscreen(bool fullscreen) override +``` + +## 中文描述 + +设置全屏模式。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `fullscreen` | `bool` | 是否全屏 | + +## 返回值 + +无 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +swapChain->SetFullscreen(true); +``` + +## 相关文档 + +- [D3D12SwapChain](swap-chain.md) - 类总览 +- [D3D12SwapChain::IsFullscreen](is-fullscreen.md) - 检查全屏状态 diff --git a/docs/api/rhi/d3d12/swap-chain/set-should-close.md b/docs/api/rhi/d3d12/swap-chain/set-should-close.md new file mode 100644 index 0000000..e14196e --- /dev/null +++ b/docs/api/rhi/d3d12/swap-chain/set-should-close.md @@ -0,0 +1,36 @@ +# D3D12SwapChain::SetShouldClose + +## 函数签名 + +```cpp +void SetShouldClose(bool shouldClose) override +``` + +## 中文描述 + +设置窗口关闭标志。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `shouldClose` | `bool` | 是否应该关闭 | + +## 返回值 + +无 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +swapChain->SetShouldClose(true); +``` + +## 相关文档 + +- [D3D12SwapChain](swap-chain.md) - 类总览 +- [D3D12SwapChain::ShouldClose](should-close.md) - 检查关闭标志 diff --git a/docs/api/rhi/d3d12/swap-chain/should-close.md b/docs/api/rhi/d3d12/swap-chain/should-close.md new file mode 100644 index 0000000..9f4beed --- /dev/null +++ b/docs/api/rhi/d3d12/swap-chain/should-close.md @@ -0,0 +1,32 @@ +# D3D12SwapChain::ShouldClose + +## 函数签名 + +```cpp +bool ShouldClose() const override +``` + +## 中文描述 + +检查窗口是否应该关闭(如收到 WM_CLOSE 消息)。 + +## 返回值 + +`bool` - 如果应该关闭则返回 `true` + +## 复杂度 + +O(1) + +## 示例 + +```cpp +if (swapChain->ShouldClose()) { + // 处理关闭 +} +``` + +## 相关文档 + +- [D3D12SwapChain](swap-chain.md) - 类总览 +- [D3D12SwapChain::SetShouldClose](set-should-close.md) - 设置关闭标志 diff --git a/docs/api/rhi/d3d12/swap-chain/swap-chain.md b/docs/api/rhi/d3d12/swap-chain/swap-chain.md new file mode 100644 index 0000000..6d74285 --- /dev/null +++ b/docs/api/rhi/d3d12/swap-chain/swap-chain.md @@ -0,0 +1,29 @@ +# D3D12SwapChain + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 交换链的 D3D12 实现,继承自 `RHISwapChain`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](initialize-from-swapchain.md) | 从交换链初始化 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭交换链 | +| [`GetCurrentBackBufferIndex`](get-current-back-buffer-index.md) | 获取当前后台缓冲区索引 | +| [`GetCurrentBackBuffer`](get-current-back-buffer.md) | 获取当前后台缓冲区 | +| [`GetBackBuffer`](get-back-buffer.md) | 获取后台缓冲区 | +| [`Present`](present.md) | 呈现画面 | +| [`Resize`](../../swap-chain/resize.md) | 调整交换链大小 | +| [`SetFullscreen`](set-fullscreen.md) | 设置全屏模式 | +| [`IsFullscreen`](is-fullscreen.md) | 检查是否全屏 | +| [`ShouldClose`](should-close.md) | 检查是否应关闭 | +| [`SetShouldClose`](set-should-close.md) | 设置关闭标志 | +| [`PollEvents`](poll-events.md) | 处理窗口事件 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | +| [`GetSwapChain`](get-swap-chain.md) | 获取 D3D12 交换链 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) +- [RHISwapChain](../../swap-chain/swap-chain.md) - 抽象交换链接口 diff --git a/docs/api/rhi/d3d12/texture/get-array-size.md b/docs/api/rhi/d3d12/texture/get-array-size.md new file mode 100644 index 0000000..2897560 --- /dev/null +++ b/docs/api/rhi/d3d12/texture/get-array-size.md @@ -0,0 +1,29 @@ +# D3D12Texture::GetArraySize + +## 函数签名 + +```cpp +uint32_t GetArraySize() const +``` + +## 中文描述 + +获取纹理数组大小。对于非数组纹理,返回 1。 + +## 返回值 + +`uint32_t` - 数组大小 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +uint32_t arraySize = texture->GetArraySize(); +``` + +## 相关文档 + +- [D3D12Texture](texture.md) - 类总览 diff --git a/docs/api/rhi/d3d12/texture/initialize-depth-stencil.md b/docs/api/rhi/d3d12/texture/initialize-depth-stencil.md new file mode 100644 index 0000000..d454283 --- /dev/null +++ b/docs/api/rhi/d3d12/texture/initialize-depth-stencil.md @@ -0,0 +1,38 @@ +# D3D12Texture::InitializeDepthStencil + +## 函数签名 + +```cpp +bool InitializeDepthStencil(ID3D12Device* device, uint32_t width, uint32_t height, DXGI_FORMAT format = DXGI_FORMAT_D24_UNORM_S8_UINT) +``` + +## 中文描述 + +初始化深度模板纹理。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `device` | `ID3D12Device*` | D3D12 设备指针 | +| `width` | `uint32_t` | 纹理宽度 | +| `height` | `uint32_t` | 纹理高度 | +| `format` | `DXGI_FORMAT` | 深度格式(默认 D24_UNORM_S8_UINT) | + +## 返回值 + +`bool` - 初始化是否成功 + +## 复杂度 + +O(n) - 取决于纹理大小 + +## 示例 + +```cpp +texture->InitializeDepthStencil(device, 1920, 1080); +``` + +## 相关文档 + +- [D3D12Texture](texture.md) - 类总览 diff --git a/docs/api/rhi/d3d12/texture/initialize-from-data.md b/docs/api/rhi/d3d12/texture/initialize-from-data.md new file mode 100644 index 0000000..393ddce --- /dev/null +++ b/docs/api/rhi/d3d12/texture/initialize-from-data.md @@ -0,0 +1,42 @@ +# D3D12Texture::InitializeFromData + +## 函数签名 + +```cpp +bool InitializeFromData(ID3D12Device* device, ID3D12GraphicsCommandList* commandList, + const void* pixelData, uint32_t width, uint32_t height, DXGI_FORMAT format) +``` + +## 中文描述 + +从像素数据初始化纹理,内部会创建上传堆并复制数据。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `device` | `ID3D12Device*` | D3D12 设备指针 | +| `commandList` | `ID3D12GraphicsCommandList*` | 命令列表指针 | +| `pixelData` | `const void*` | 像素数据指针 | +| `width` | `uint32_t` | 纹理宽度 | +| `height` | `uint32_t` | 纹理高度 | +| `format` | `DXGI_FORMAT` | 像素格式 | + +## 返回值 + +`bool` - 初始化是否成功 + +## 复杂度 + +O(n) - 取决于纹理大小,内部创建临时上传堆 + +## 示例 + +```cpp +std::vector pixels = LoadImage("texture.png"); +texture->InitializeFromData(device, cmdList, pixels.data(), width, height, DXGI_FORMAT_R8G8B8A8_UNORM); +``` + +## 相关文档 + +- [D3D12Texture](texture.md) - 类总览 diff --git a/docs/api/rhi/d3d12/texture/texture.md b/docs/api/rhi/d3d12/texture/texture.md new file mode 100644 index 0000000..fe55dfa --- /dev/null +++ b/docs/api/rhi/d3d12/texture/texture.md @@ -0,0 +1,35 @@ +# D3D12Texture + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 纹理的 D3D12 实现,继承自 `RHITexture`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`InitializeFromExisting`](../buffer/initialize-from-existing.md) | 从现有资源初始化 | +| [`InitializeFromData`](initialize-from-data.md) | 从数据初始化纹理 | +| [`InitializeDepthStencil`](initialize-depth-stencil.md) | 初始化深度模板纹理 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭纹理 | +| [`GetResource`](../buffer/get-resource.md) | 获取 D3D12 资源 | +| [`GetDesc`](../buffer/get-desc.md) | 获取纹理描述符 | +| [`GetWidth`](../../texture/get-width.md) | 获取纹理宽度 | +| [`GetHeight`](../../texture/get-height.md) | 获取纹理高度 | +| [`GetDepth`](../../texture/get-depth.md) | 获取纹理深度 | +| [`GetMipLevels`](../../texture/get-mip-levels.md) | 获取 Mip 级别 | +| [`GetArraySize`](get-array-size.md) | 获取数组大小 | +| [`GetGPUAddress`](../buffer/get-gpu-address.md) | 获取 GPU 地址 | +| [`GetSize`](../../buffer/get-size.md) | 获取纹理大小 | +| [`GetName`](../../buffer/get-name.md) | 获取纹理名称 | +| [`SetName`](../../buffer/set-name.md) | 设置纹理名称 | +| [`GetFormat`](../../texture/get-format.md) | 获取纹理格式 | +| [`GetTextureType`](../../texture/get-texture-type.md) | 获取纹理类型 | +| [`GetState`](../../buffer/get-state.md) | 获取资源状态 | +| [`SetState`](../../buffer/set-state.md) | 设置资源状态 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) +- [RHITexture](../../texture/texture.md) - 抽象纹理接口 diff --git a/docs/api/rhi/d3d12/types/to-d3d12-buffer-desc.md b/docs/api/rhi/d3d12/types/to-d3d12-buffer-desc.md new file mode 100644 index 0000000..f5e09f4 --- /dev/null +++ b/docs/api/rhi/d3d12/types/to-d3d12-buffer-desc.md @@ -0,0 +1,36 @@ +# ToD3D12(BufferDesc) + +## 函数签名 + +```cpp +inline D3D12_RESOURCE_DESC ToD3D12(const BufferDesc& desc) +``` + +## 中文描述 + +将 RHI BufferDesc 转换为 D3D12_RESOURCE_DESC。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `desc` | `const BufferDesc&` | RHI 缓冲区描述引用 | + +## 返回值 + +`D3D12_RESOURCE_DESC` - D3D12 资源描述结构 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +BufferDesc bd = { 1024 }; +D3D12_RESOURCE_DESC d3d12Desc = ToD3D12(bd); +``` + +## 相关文档 + +- [D3D12Types](types.md) - 类型总览 diff --git a/docs/api/rhi/d3d12/types/to-d3d12-clear-value.md b/docs/api/rhi/d3d12/types/to-d3d12-clear-value.md new file mode 100644 index 0000000..c46bd79 --- /dev/null +++ b/docs/api/rhi/d3d12/types/to-d3d12-clear-value.md @@ -0,0 +1,37 @@ +# ToD3D12(ClearValue) + +## 函数签名 + +```cpp +inline D3D12_CLEAR_VALUE ToD3D12(const ClearValue& clearValue, D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE) +``` + +## 中文描述 + +将 RHI ClearValue 转换为 D3D12_CLEAR_VALUE。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `clearValue` | `const ClearValue&` | RHI ClearValue 引用 | +| `flags` | `D3D12_RESOURCE_FLAGS` | 资源标志(默认 NONE) | + +## 返回值 + +`D3D12_CLEAR_VALUE` - D3D12 清除值结构 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +ClearValue cv = { { 0.0f, 0.0f, 0.0f, 1.0f } }; +D3D12_CLEAR_VALUE d3d12CV = ToD3D12(cv); +``` + +## 相关文档 + +- [D3D12Types](types.md) - 类型总览 diff --git a/docs/api/rhi/d3d12/types/to-d3d12-command-queue-desc.md b/docs/api/rhi/d3d12/types/to-d3d12-command-queue-desc.md new file mode 100644 index 0000000..4803e3a --- /dev/null +++ b/docs/api/rhi/d3d12/types/to-d3d12-command-queue-desc.md @@ -0,0 +1,36 @@ +# ToD3D12(CommandQueueDesc) + +## 函数签名 + +```cpp +inline D3D12_COMMAND_QUEUE_DESC ToD3D12(const CommandQueueDesc& desc) +``` + +## 中文描述 + +将 RHI CommandQueueDesc 转换为 D3D12_COMMAND_QUEUE_DESC。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `desc` | `const CommandQueueDesc&` | RHI 命令队列描述引用 | + +## 返回值 + +`D3D12_COMMAND_QUEUE_DESC` - D3D12 命令队列描述结构 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +CommandQueueDesc cqd = { CommandQueueType::Graphics }; +D3D12_COMMAND_QUEUE_DESC d3d12Desc = ToD3D12(cqd); +``` + +## 相关文档 + +- [D3D12Types](types.md) - 类型总览 diff --git a/docs/api/rhi/d3d12/types/to-d3d12-depth-stencil.md b/docs/api/rhi/d3d12/types/to-d3d12-depth-stencil.md new file mode 100644 index 0000000..80b8085 --- /dev/null +++ b/docs/api/rhi/d3d12/types/to-d3d12-depth-stencil.md @@ -0,0 +1,37 @@ +# ToD3D12DepthStencil + +## 函数签名 + +```cpp +inline D3D12_CLEAR_VALUE ToD3D12DepthStencil(const ClearValue& clearValue, DXGI_FORMAT format) +``` + +## 中文描述 + +将 RHI ClearValue 转换为 D3D12 深度模板清除值。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `clearValue` | `const ClearValue&` | RHI ClearValue 引用 | +| `format` | `DXGI_FORMAT` | 深度格式 | + +## 返回值 + +`D3D12_CLEAR_VALUE` - D3D12 清除值结构 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +ClearValue cv = { 1.0f, 0 }; +D3D12_CLEAR_VALUE d3d12CV = ToD3D12DepthStencil(cv, DXGI_FORMAT_D24_UNORM_S8_UINT); +``` + +## 相关文档 + +- [D3D12Types](types.md) - 类型总览 diff --git a/docs/api/rhi/d3d12/types/to-d3d12-descriptor-heap-desc.md b/docs/api/rhi/d3d12/types/to-d3d12-descriptor-heap-desc.md new file mode 100644 index 0000000..1eb2bae --- /dev/null +++ b/docs/api/rhi/d3d12/types/to-d3d12-descriptor-heap-desc.md @@ -0,0 +1,36 @@ +# ToD3D12(DescriptorHeapDesc) + +## 函数签名 + +```cpp +inline D3D12_DESCRIPTOR_HEAP_DESC ToD3D12(const DescriptorHeapDesc& desc) +``` + +## 中文描述 + +将 RHI DescriptorHeapDesc 转换为 D3D12_DESCRIPTOR_HEAP_DESC。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `desc` | `const DescriptorHeapDesc&` | RHI 描述符堆描述引用 | + +## 返回值 + +`D3D12_DESCRIPTOR_HEAP_DESC` - D3D12 描述符堆描述结构 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +DescriptorHeapDesc dhd = { DescriptorHeapType::CBV_SRV_UAV, 100 }; +D3D12_DESCRIPTOR_HEAP_DESC d3d12Desc = ToD3D12(dhd); +``` + +## 相关文档 + +- [D3D12Types](types.md) - 类型总览 diff --git a/docs/api/rhi/d3d12/types/to-d3d12-heap-properties.md b/docs/api/rhi/d3d12/types/to-d3d12-heap-properties.md new file mode 100644 index 0000000..ec0a02a --- /dev/null +++ b/docs/api/rhi/d3d12/types/to-d3d12-heap-properties.md @@ -0,0 +1,36 @@ +# ToD3D12HeapProperties + +## 函数签名 + +```cpp +inline D3D12_HEAP_PROPERTIES ToD3D12HeapProperties(D3D12_HEAP_TYPE heapType, UINT nodeMask = 0) +``` + +## 中文描述 + +将 D3D12_HEAP_TYPE 转换为 D3D12_HEAP_PROPERTIES。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `heapType` | `D3D12_HEAP_TYPE` | D3D12 堆类型 | +| `nodeMask` | `UINT` | 节点掩码(默认 0) | + +## 返回值 + +`D3D12_HEAP_PROPERTIES` - D3D12 堆属性结构 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_HEAP_PROPERTIES props = ToD3D12HeapProperties(D3D12_HEAP_TYPE_DEFAULT); +``` + +## 相关文档 + +- [D3D12Types](types.md) - 类型总览 diff --git a/docs/api/rhi/d3d12/types/to-d3d12-rect.md b/docs/api/rhi/d3d12/types/to-d3d12-rect.md new file mode 100644 index 0000000..9eb004e --- /dev/null +++ b/docs/api/rhi/d3d12/types/to-d3d12-rect.md @@ -0,0 +1,36 @@ +# ToD3D12(Rect) + +## 函数签名 + +```cpp +inline D3D12_RECT ToD3D12(const Rect& rect) +``` + +## 中文描述 + +将 RHI Rect 转换为 D3D12_RECT。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `rect` | `const Rect&` | RHI Rect 引用 | + +## 返回值 + +`D3D12_RECT` - D3D12 矩形结构 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +Rect r = { 0, 0, 1920, 1080 }; +D3D12_RECT d3d12Rect = ToD3D12(r); +``` + +## 相关文档 + +- [D3D12Types](types.md) - 类型总览 diff --git a/docs/api/rhi/d3d12/types/to-d3d12-texture-desc.md b/docs/api/rhi/d3d12/types/to-d3d12-texture-desc.md new file mode 100644 index 0000000..4d059a6 --- /dev/null +++ b/docs/api/rhi/d3d12/types/to-d3d12-texture-desc.md @@ -0,0 +1,36 @@ +# ToD3D12(TextureDesc) + +## 函数签名 + +```cpp +inline D3D12_RESOURCE_DESC ToD3D12(const TextureDesc& desc) +``` + +## 中文描述 + +将 RHI TextureDesc 转换为 D3D12_RESOURCE_DESC。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `desc` | `const TextureDesc&` | RHI 纹理描述引用 | + +## 返回值 + +`D3D12_RESOURCE_DESC` - D3D12 资源描述结构 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +TextureDesc td = { TextureType::Texture2D, 1920, 1080, 1, Format::R8G8B8A8_UNorm }; +D3D12_RESOURCE_DESC d3d12Desc = ToD3D12(td); +``` + +## 相关文档 + +- [D3D12Types](types.md) - 类型总览 diff --git a/docs/api/rhi/d3d12/types/to-d3d12-viewport.md b/docs/api/rhi/d3d12/types/to-d3d12-viewport.md new file mode 100644 index 0000000..95a5302 --- /dev/null +++ b/docs/api/rhi/d3d12/types/to-d3d12-viewport.md @@ -0,0 +1,36 @@ +# ToD3D12(Viewport) + +## 函数签名 + +```cpp +inline D3D12_VIEWPORT ToD3D12(const Viewport& vp) +``` + +## 中文描述 + +将 RHI Viewport 转换为 D3D12_VIEWPORT。 + +## 参数 + +| 参数 | 类型 | 描述 | +|------|------|------| +| `vp` | `const Viewport&` | RHI Viewport 引用 | + +## 返回值 + +`D3D12_VIEWPORT` - D3D12 视口结构 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +Viewport vp = { 0, 0, 1920, 1080, 0.0f, 1.0f }; +D3D12_VIEWPORT d3d12Vp = ToD3D12(vp); +``` + +## 相关文档 + +- [D3D12Types](types.md) - 类型总览 diff --git a/docs/api/rhi/d3d12/types/types.md b/docs/api/rhi/d3d12/types/types.md new file mode 100644 index 0000000..d4a60a2 --- /dev/null +++ b/docs/api/rhi/d3d12/types/types.md @@ -0,0 +1,24 @@ +# D3D12Types + +**命名空间**: `XCEngine::RHI` + +**描述**: D3D12 类型转换和辅助函数集合,提供 RHI 抽象类型到 D3D12 类型的转换。**所有函数均为 inline 函数**。 + +## 转换函数列表 + +| 函数 | 文档 | +|------|------| +| `ToD3D12(Viewport)` | [详细文档](to-d3d12-viewport.md) | +| `ToD3D12(Rect)` | [详细文档](to-d3d12-rect.md) | +| `ToD3D12(ClearValue)` | [详细文档](to-d3d12-clear-value.md) | +| `ToD3D12DepthStencil` | [详细文档](to-d3d12-depth-stencil.md) | +| `ToD3D12(TextureDesc)` | [详细文档](to-d3d12-texture-desc.md) | +| `ToD3D12(BufferDesc)` | [详细文档](to-d3d12-buffer-desc.md) | +| `ToD3D12(DescriptorHeapDesc)` | [详细文档](to-d3d12-descriptor-heap-desc.md) | +| `ToD3D12(CommandQueueDesc)` | [详细文档](to-d3d12-command-queue-desc.md) | +| `ToD3D12HeapProperties` | [详细文档](to-d3d12-heap-properties.md) | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) +- [D3D12Enum](../../enums/enums.md) - 枚举值转换 diff --git a/docs/api/rhi/d3d12/unordered-access-view/get-cpu-descriptor-handle.md b/docs/api/rhi/d3d12/unordered-access-view/get-cpu-descriptor-handle.md new file mode 100644 index 0000000..105b13d --- /dev/null +++ b/docs/api/rhi/d3d12/unordered-access-view/get-cpu-descriptor-handle.md @@ -0,0 +1,29 @@ +# D3D12UnorderedAccessView::GetCPUDescriptorHandle + +## 函数签名 + +```cpp +D3D12_CPU_DESCRIPTOR_HANDLE GetCPUDescriptorHandle() const +``` + +## 中文描述 + +获取无序访问视图的 CPU 描述符句柄。 + +## 返回值 + +`D3D12_CPU_DESCRIPTOR_HANDLE` - CPU 描述符句柄 + +## 复杂度 + +O(1) + +## 示例 + +```cpp +D3D12_CPU_DESCRIPTOR_HANDLE handle = uav->GetCPUDescriptorHandle(); +``` + +## 相关文档 + +- [D3D12UnorderedAccessView](unordered-access-view.md) - 类总览 diff --git a/docs/api/rhi/d3d12/unordered-access-view/unordered-access-view.md b/docs/api/rhi/d3d12/unordered-access-view/unordered-access-view.md new file mode 100644 index 0000000..05ec467 --- /dev/null +++ b/docs/api/rhi/d3d12/unordered-access-view/unordered-access-view.md @@ -0,0 +1,15 @@ +# D3D12UnorderedAccessView + +**命名空间**: `XCEngine::RHI` + +**描述**: DirectX 12 无序访问视图的 D3D12 实现。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`GetCPUDescriptorHandle`](get-cpu-descriptor-handle.md) | 获取 CPU 描述符句柄 | + +## 相关文档 + +- [D3D12 后端总览](../../opengl/overview.md) diff --git a/docs/api/rhi/descriptor-pool/descriptor-pool.md b/docs/api/rhi/descriptor-pool/descriptor-pool.md new file mode 100644 index 0000000..cc9ce68 --- /dev/null +++ b/docs/api/rhi/descriptor-pool/descriptor-pool.md @@ -0,0 +1,22 @@ +# RHIDescriptorPool + +**命名空间**: `XCEngine::RHI` + +**类型**: `class` (abstract) + +**描述**: GPU 描述符堆池抽象接口,用于管理 GPU 描述符的分配和回收。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../threading/task-system/initialize.md) | 初始化描述符池 | +| [`Shutdown`](../../threading/task-system/shutdown.md) | 关闭并释放资源 | +| [`GetNativeHandle`](../buffer/get-native-handle.md) | 获取原生句柄 | +| [`GetDescriptorCount`](get-descriptor-count.md) | 获取描述符数量 | +| [`GetType`](../command-queue/get-type.md) | 获取描述符类型 | + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHIDevice](../device/device.md) - 创建设备 diff --git a/docs/api/rhi/descriptor-pool/get-descriptor-count.md b/docs/api/rhi/descriptor-pool/get-descriptor-count.md new file mode 100644 index 0000000..2505223 --- /dev/null +++ b/docs/api/rhi/descriptor-pool/get-descriptor-count.md @@ -0,0 +1,19 @@ +# RHIDescriptorPool::GetDescriptorCount + +```cpp +virtual uint32_t GetDescriptorCount() const = 0; +``` + +获取描述符数量。 + +**返回:** 描述符池中的描述符数量 + +**示例:** + +```cpp +uint32_t count = descriptorPool->GetDescriptorCount(); +``` + +## 相关文档 + +- [RHIDescriptorPool 总览](descriptor-pool.md) - 返回类总览 diff --git a/docs/api/rhi/descriptor-pool/methods.md b/docs/api/rhi/descriptor-pool/methods.md new file mode 100644 index 0000000..dcda05d --- /dev/null +++ b/docs/api/rhi/descriptor-pool/methods.md @@ -0,0 +1,41 @@ +# RHIDescriptorPool 方法 + +## Initialize + +```cpp +virtual bool Initialize(const DescriptorPoolDesc& desc) = 0; +``` + +初始化描述符池。 + +## Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +释放描述符池资源。 + +## GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 + +## GetDescriptorCount + +```cpp +virtual uint32_t GetDescriptorCount() const = 0; +``` + +获取描述符数量。 + +## GetType + +```cpp +virtual DescriptorHeapType GetType() const = 0; +``` + +获取堆类型。 diff --git a/docs/api/rhi/device/compile-shader.md b/docs/api/rhi/device/compile-shader.md new file mode 100644 index 0000000..e577171 --- /dev/null +++ b/docs/api/rhi/device/compile-shader.md @@ -0,0 +1,35 @@ +# RHIDevice::CompileShader + +```cpp +virtual RHIShader* CompileShader(const ShaderCompileDesc& desc) = 0; +``` + +编译着色器程序。 + +**参数:** +- `desc` - 着色器编译描述符,包含入口点、配置文件、源文件等 + +**返回:** 新创建的着色器指针,失败返回 `nullptr` + +**复杂度:** O(n) - 取决于着色器代码复杂度 + +**示例:** + +```cpp +ShaderCompileDesc shaderDesc; +shaderDesc.entryPoint = L"main"; +shaderDesc.profile = L"vs_6_0"; +shaderDesc.fileName = L"shaders/vertex.hlsl"; +shaderDesc.macros = {}; + +RHIShader* vertexShader = device->CompileShader(shaderDesc); +if (!vertexShader->IsValid()) { + // 处理编译错误 + vertexShader->Shutdown(); +} +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 +- [RHIShader](../shader/shader.md) - 着色器类 diff --git a/docs/api/rhi/device/create-buffer.md b/docs/api/rhi/device/create-buffer.md new file mode 100644 index 0000000..a246941 --- /dev/null +++ b/docs/api/rhi/device/create-buffer.md @@ -0,0 +1,32 @@ +# RHIDevice::CreateBuffer + +```cpp +virtual RHIBuffer* CreateBuffer(const BufferDesc& desc) = 0; +``` + +创建 GPU 缓冲区资源。 + +**参数:** +- `desc` - 缓冲区描述符,包含大小、类型、标志等 + +**返回:** 新创建的缓冲区指针,失败返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +BufferDesc bufferDesc; +bufferDesc.size = sizeof(Vertex) * vertexCount; +bufferDesc.stride = sizeof(Vertex); +bufferDesc.bufferType = (uint32_t)BufferType::Vertex; +bufferDesc.flags = 0; + +RHIBuffer* vertexBuffer = device->CreateBuffer(bufferDesc); +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 +- [RHIBuffer](../buffer/buffer.md) - 缓冲区类 +- [BufferDesc](../types/types.md) - 缓冲区描述结构体 diff --git a/docs/api/rhi/device/create-command-list.md b/docs/api/rhi/device/create-command-list.md new file mode 100644 index 0000000..2c04e66 --- /dev/null +++ b/docs/api/rhi/device/create-command-list.md @@ -0,0 +1,29 @@ +# RHIDevice::CreateCommandList + +```cpp +virtual RHICommandList* CreateCommandList(const CommandListDesc& desc) = 0; +``` + +创建命令列表,用于录制 GPU 命令。 + +**参数:** +- `desc` - 命令列表描述符,包含类型和节点掩码 + +**返回:** 新创建的命令列表指针,失败返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +CommandListDesc cmdListDesc; +cmdListDesc.commandListType = (uint32_t)CommandQueueType::Direct; +cmdListDesc.nodeMask = 0; + +RHICommandList* commandList = device->CreateCommandList(cmdListDesc); +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 +- [RHICommandList](../command-list/command-list.md) - 命令列表类 diff --git a/docs/api/rhi/device/create-command-queue.md b/docs/api/rhi/device/create-command-queue.md new file mode 100644 index 0000000..874317b --- /dev/null +++ b/docs/api/rhi/device/create-command-queue.md @@ -0,0 +1,31 @@ +# RHIDevice::CreateCommandQueue + +```cpp +virtual RHICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) = 0; +``` + +创建命令队列,用于提交和执行命令列表。 + +**参数:** +- `desc` - 命令队列描述符,包含队列类型和优先级 + +**返回:** 新创建的命令队列指针,失败返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +CommandQueueDesc queueDesc; +queueDesc.queueType = (uint32_t)CommandQueueType::Direct; +queueDesc.priority = 0; +queueDesc.nodeMask = 0; +queueDesc.flags = 0; + +RHICommandQueue* commandQueue = device->CreateCommandQueue(queueDesc); +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 +- [RHICommandQueue](../command-queue/command-queue.md) - 命令队列类 diff --git a/docs/api/rhi/device/create-fence.md b/docs/api/rhi/device/create-fence.md new file mode 100644 index 0000000..a0345cf --- /dev/null +++ b/docs/api/rhi/device/create-fence.md @@ -0,0 +1,29 @@ +# RHIDevice::CreateFence + +```cpp +virtual RHIFence* CreateFence(const FenceDesc& desc) = 0; +``` + +创建同步栅栏,用于 CPU/GPU 同步。 + +**参数:** +- `desc` - 栅栏描述符,包含初始值和标志 + +**返回:** 新创建的栅栏指针,失败返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +FenceDesc fenceDesc; +fenceDesc.initialValue = 0; +fenceDesc.flags = 0; + +RHIFence* fence = device->CreateFence(fenceDesc); +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 +- [RHIFence](../fence/fence.md) - 栅栏类 diff --git a/docs/api/rhi/device/create-pipeline-state.md b/docs/api/rhi/device/create-pipeline-state.md new file mode 100644 index 0000000..ab6beae --- /dev/null +++ b/docs/api/rhi/device/create-pipeline-state.md @@ -0,0 +1,29 @@ +# RHIDevice::CreatePipelineState + +```cpp +virtual RHIPipelineState* CreatePipelineState(const PipelineStateDesc& desc) = 0; +``` + +创建渲染管线状态对象(PSO)。 + +**参数:** +- `desc` - 管线状态描述符,包含编译好的着色器字节码 + +**返回:** 新创建的管线状态指针,失败返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +PipelineStateDesc psoDesc; +psoDesc.pBlob = compiledShaderBytecode; +psoDesc.size = bytecodeSize; + +RHIPipelineState* pipelineState = device->CreatePipelineState(psoDesc); +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 +- [RHIPipelineState](../pipeline-state/pipeline-state.md) - 管线状态类 diff --git a/docs/api/rhi/device/create-sampler.md b/docs/api/rhi/device/create-sampler.md new file mode 100644 index 0000000..2d0a6df --- /dev/null +++ b/docs/api/rhi/device/create-sampler.md @@ -0,0 +1,34 @@ +# RHIDevice::CreateSampler + +```cpp +virtual RHISampler* CreateSampler(const SamplerDesc& desc) = 0; +``` + +创建纹理采样器。 + +**参数:** +- `desc` - 采样器描述符,包含过滤模式、寻址模式等 + +**返回:** 新创建的采样器指针,失败返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +SamplerDesc samplerDesc; +samplerDesc.filter = (uint32_t)FilterMode::Anisotropic; +samplerDesc.addressU = (uint32_t)TextureAddressMode::Wrap; +samplerDesc.addressV = (uint32_t)TextureAddressMode::Wrap; +samplerDesc.addressW = (uint32_t)TextureAddressMode::Wrap; +samplerDesc.maxAnisotropy = 16; +samplerDesc.minLod = 0; +samplerDesc.maxLod = FLT_MAX; + +RHISampler* sampler = device->CreateSampler(samplerDesc); +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 +- [RHISampler](../sampler/sampler.md) - 采样器类 diff --git a/docs/api/rhi/device/create-swap-chain.md b/docs/api/rhi/device/create-swap-chain.md new file mode 100644 index 0000000..63c9663 --- /dev/null +++ b/docs/api/rhi/device/create-swap-chain.md @@ -0,0 +1,34 @@ +# RHIDevice::CreateSwapChain + +```cpp +virtual RHISwapChain* CreateSwapChain(const SwapChainDesc& desc) = 0; +``` + +创建交换链,用于管理窗口渲染和帧缓冲区切换。 + +**参数:** +- `desc` - 交换链描述符,包含尺寸、缓冲数量、格式等 + +**返回:** 新创建的交换链指针,失败返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +SwapChainDesc swapChainDesc; +swapChainDesc.width = 1280; +swapChainDesc.height = 720; +swapChainDesc.bufferCount = 2; +swapChainDesc.format = (uint32_t)Format::R8G8B8A8_UNorm; +swapChainDesc.refreshRate = 60; +swapChainDesc.sampleCount = 1; +swapChainDesc.sampleQuality = 0; + +RHISwapChain* swapChain = device->CreateSwapChain(swapChainDesc); +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 +- [RHISwapChain](../swap-chain/swap-chain.md) - 交换链类 diff --git a/docs/api/rhi/device/create-texture.md b/docs/api/rhi/device/create-texture.md new file mode 100644 index 0000000..6887602 --- /dev/null +++ b/docs/api/rhi/device/create-texture.md @@ -0,0 +1,38 @@ +# RHIDevice::CreateTexture + +```cpp +virtual RHITexture* CreateTexture(const TextureDesc& desc) = 0; +``` + +创建 GPU 纹理资源。 + +**参数:** +- `desc` - 纹理描述符,包含尺寸、格式、纹理类型等 + +**返回:** 新创建的纹理指针,失败返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +TextureDesc textureDesc; +textureDesc.width = 1024; +textureDesc.height = 1024; +textureDesc.depth = 1; +textureDesc.mipLevels = 1; +textureDesc.arraySize = 1; +textureDesc.format = (uint32_t)Format::R8G8B8A8_UNorm; +textureDesc.textureType = (uint32_t)TextureType::Texture2D; +textureDesc.sampleCount = 1; +textureDesc.sampleQuality = 0; +textureDesc.flags = 0; + +RHITexture* texture = device->CreateTexture(textureDesc); +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 +- [RHITexture](../texture/texture.md) - 纹理类 +- [TextureDesc](../types/types.md) - 纹理描述结构体 diff --git a/docs/api/rhi/device/device.md b/docs/api/rhi/device/device.md new file mode 100644 index 0000000..cbe249d --- /dev/null +++ b/docs/api/rhi/device/device.md @@ -0,0 +1,73 @@ +# RHIDevice + +**命名空间**: `XCEngine::RHI` + +**类型**: `class` (abstract) + +**描述**: RHI 渲染设备抽象接口,代表一个图形设备实例。 + +## 概述 + +`RHIDevice` 是 RHI 模块的核心接口之一,负责创建和管理所有 GPU 资源。每个 RHI 后端(D3D12、OpenGL 等)都需要实现此接口。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](initialize.md) | 初始化设备 | +| [`Shutdown`](shutdown.md) | 关闭设备 | +| [`CreateBuffer`](create-buffer.md) | 创建缓冲区 | +| [`CreateTexture`](create-texture.md) | 创建纹理 | +| [`CreateSwapChain`](create-swap-chain.md) | 创建交换链 | +| [`CreateCommandList`](create-command-list.md) | 创建命令列表 | +| [`CreateCommandQueue`](create-command-queue.md) | 创建命令队列 | +| [`CompileShader`](compile-shader.md) | 编译着色器 | +| [`CreatePipelineState`](create-pipeline-state.md) | 创建管线状态 | +| [`CreateFence`](create-fence.md) | 创建栅栏 | +| [`CreateSampler`](create-sampler.md) | 创建采样器 | +| [`GetCapabilities`](get-capabilities.md) | 获取设备能力 | +| [`GetDeviceInfo`](get-device-info.md) | 获取设备信息 | +| [`GetNativeDevice`](get-native-device.md) | 获取原生设备 | + +## 使用示例 + +```cpp +// 创建 D3D12 设备 +RHI::RHIDevice* device = RHI::RHIFactory::CreateRHIDevice(RHI::RHIType::D3D12); + +// 配置设备描述 +RHI::RHIDeviceDesc desc; +desc.windowHandle = hwnd; +desc.width = 1280; +desc.height = 720; +desc.appName = L"MyApp"; +desc.enableDebugLayer = true; + +// 初始化设备 +if (device->Initialize(desc)) { + const RHI::RHICapabilities& caps = device->GetCapabilities(); + if (caps.bSupportsRayTracing) { + // 设备支持光线追踪 + } + + const RHI::RHIDeviceInfo& info = device->GetDeviceInfo(); + printf("GPU: %ls\n", info.description.c_str()); + + // 创建资源 + RHI::BufferDesc bufferDesc; + bufferDesc.size = 1024; + bufferDesc.bufferType = (uint32_t)RHI::BufferType::Vertex; + RHI::RHIBuffer* buffer = device->CreateBuffer(bufferDesc); + + device->Shutdown(); +} + +delete device; +``` + +## 相关文档 + +- [../../rhi.md](../rhi.md) - RHI 模块总览 +- [RHIFactory](../factory/factory.md) - 设备工厂 +- [RHICapabilities](../capabilities/capabilities.md) - 设备能力 +- [RHITypes](../types/types.md) - 设备描述结构体 diff --git a/docs/api/rhi/device/get-capabilities.md b/docs/api/rhi/device/get-capabilities.md new file mode 100644 index 0000000..1012565 --- /dev/null +++ b/docs/api/rhi/device/get-capabilities.md @@ -0,0 +1,32 @@ +# RHIDevice::GetCapabilities + +```cpp +virtual const RHICapabilities& GetCapabilities() const = 0; +``` + +获取当前设备的图形能力。 + +**返回:** 设备能力结构体引用 + +**复杂度:** O(1) + +**示例:** + +```cpp +const RHICapabilities& caps = device->GetCapabilities(); + +if (caps.bSupportsRayTracing) { + // 启用光线追踪功能 +} + +if (caps.bSupportsComputeShaders) { + // 启用计算着色器 +} + +uint32_t maxTexSize = caps.maxTexture2DSize; +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 +- [RHICapabilities](../capabilities/capabilities.md) - 设备能力类 diff --git a/docs/api/rhi/device/get-device-info.md b/docs/api/rhi/device/get-device-info.md new file mode 100644 index 0000000..94b67d2 --- /dev/null +++ b/docs/api/rhi/device/get-device-info.md @@ -0,0 +1,27 @@ +# RHIDevice::GetDeviceInfo + +```cpp +virtual const RHIDeviceInfo& GetDeviceInfo() const = 0; +``` + +获取当前设备的详细信息。 + +**返回:** 设备信息结构体引用 + +**复杂度:** O(1) + +**示例:** + +```cpp +const RHIDeviceInfo& info = device->GetDeviceInfo(); + +printf("GPU: %ls\n", info.description.c_str()); +printf("Vendor: %ls\n", info.vendor.c_str()); +printf("Driver: %ls\n", info.version.c_str()); +printf("VRAM: %llu MB\n", info.dedicatedVideoMemory / 1024 / 1024); +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 +- [RHIDeviceInfo](../types/types.md) - 设备信息结构体 diff --git a/docs/api/rhi/device/get-native-device.md b/docs/api/rhi/device/get-native-device.md new file mode 100644 index 0000000..477396b --- /dev/null +++ b/docs/api/rhi/device/get-native-device.md @@ -0,0 +1,29 @@ +# RHIDevice::GetNativeDevice + +```cpp +virtual void* GetNativeDevice() = 0; +``` + +获取原生图形 API 设备指针。 + +**返回:** +- D3D12 后端: `ID3D12Device*` +- OpenGL 后端: `void*` (GLFWwindow* 或 GL 上下文指针) + +**复杂度:** O(1) + +**示例:** + +```cpp +void* nativeDevice = device->GetNativeDevice(); + +// D3D12 使用 +ID3D12Device* d3d12Device = static_cast(nativeDevice); + +// OpenGL 使用 +GLFWwindow* glfwWindow = static_cast(nativeDevice); +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 diff --git a/docs/api/rhi/device/initialize.md b/docs/api/rhi/device/initialize.md new file mode 100644 index 0000000..54470eb --- /dev/null +++ b/docs/api/rhi/device/initialize.md @@ -0,0 +1,39 @@ +# RHIDevice::Initialize + +```cpp +virtual bool Initialize(const RHIDeviceDesc& desc) = 0; +``` + +初始化 RHI 设备,建立与图形适配器的连接。 + +**参数:** +- `desc` - 设备描述符,包含窗口句柄、分辨率、调试选项等配置 + +**返回:** 成功返回 `true`,失败返回 `false` + +**复杂度:** O(1) + +**示例:** + +```cpp +RHIDeviceDesc desc; +desc.windowHandle = hwnd; +desc.width = 1920; +desc.height = 1080; +desc.appName = L"MyApp"; +desc.enableDebugLayer = true; +desc.enableGPUValidation = true; + +RHIDevice* device = RHIFactory::CreateRHIDevice(RHIType::D3D12); +if (device->Initialize(desc)) { + // 设备初始化成功 +} else { + // 处理初始化失败 + delete device; +} +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 +- [RHIDeviceDesc](../types/types.md) - 设备描述结构体 diff --git a/docs/api/rhi/device/shutdown.md b/docs/api/rhi/device/shutdown.md new file mode 100644 index 0000000..60d9b00 --- /dev/null +++ b/docs/api/rhi/device/shutdown.md @@ -0,0 +1,20 @@ +# RHIDevice::Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +关闭 RHI 设备,释放所有相关资源。 + +**复杂度:** O(n) - 取决于管理的资源数量 + +**示例:** + +```cpp +device->Shutdown(); +delete device; +``` + +## 相关文档 + +- [RHIDevice 总览](device.md) - 返回类总览 diff --git a/docs/api/rhi/enums/enums.md b/docs/api/rhi/enums/enums.md new file mode 100644 index 0000000..e3b72b2 --- /dev/null +++ b/docs/api/rhi/enums/enums.md @@ -0,0 +1,46 @@ +# RHIEnums + +**命名空间**: `XCEngine::RHI` + +**类型**: `enums` + +**描述**: RHI 模块中使用的所有枚举类型汇总。 + +## 主要枚举 + +| 枚举 | 描述 | +|------|------| +| `ShaderType` | 着色器类型 | +| `ShaderVisibility` | 着色器可见性 | +| `CullMode` | 背面剔除模式 | +| `FillMode` | 填充模式 | +| `BlendOp` | 混合操作 | +| `BlendFactor` | 混合因子 | +| `ComparisonFunc` | 比较函数 | +| `StencilOp` | 模板操作 | +| `PrimitiveTopology` | 图元拓扑 | +| `TextureType` | 纹理类型 | +| `Format` | 纹理/缓冲区格式 | +| `FilterMode` | 采样器过滤模式 | +| `TextureAddressMode` | 纹理寻址模式 | +| `BorderColor` | 边框颜色 | +| `BufferType` | 缓冲区类型 | +| `ResourceStates` | 资源状态 | +| `HeapType` | 内存堆类型 | +| `DescriptorType` | 描述符类型 | +| `DescriptorHeapType` | 描述符堆类型 | +| `CommandQueueType` | 命令队列类型 | +| `PipelineType` | 管线类型 | +| `LoadAction` | 加载操作 | +| `StoreAction` | 存储操作 | +| `PresentFlags` | 呈现标志 | +| `QueryType` | 查询类型 | +| `RootParameterType` | 根参数类型 | +| `LogicOp` | 逻辑操作 | +| `ColorWriteMask` | 颜色写入掩码 | +| `RHIType` | RHI 后端类型 | + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHITypes](../types/types.md) - 结构体类型汇总 diff --git a/docs/api/rhi/factory/create-rhi-device-string.md b/docs/api/rhi/factory/create-rhi-device-string.md new file mode 100644 index 0000000..36810bf --- /dev/null +++ b/docs/api/rhi/factory/create-rhi-device-string.md @@ -0,0 +1,31 @@ +# RHIFactory::CreateRHIDevice (string) + +```cpp +static RHIDevice* CreateRHIDevice(const std::string& typeName); +``` + +根据字符串名称创建 RHI 设备。 + +**参数:** +- `typeName` - 后端类型名称字符串(不区分大小写) + +**返回:** 新创建的设备指针,失败返回 `nullptr` + +**复杂度:** O(1) + +**支持的类型名称:** +- `"D3D12"` / `"d3d12"` +- `"OpenGL"` / `"opengl"` / `"GL"` +- Vulkan 和 Metal 暂不支持 + +**示例:** + +```cpp +// 从配置文件读取后端类型 +std::string backendType = "D3D12"; +RHIDevice* device = RHIFactory::CreateRHIDevice(backendType); +``` + +## 相关文档 + +- [RHIFactory 总览](factory.md) - 返回类总览 diff --git a/docs/api/rhi/factory/create-rhi-device-type.md b/docs/api/rhi/factory/create-rhi-device-type.md new file mode 100644 index 0000000..deaeb84 --- /dev/null +++ b/docs/api/rhi/factory/create-rhi-device-type.md @@ -0,0 +1,28 @@ +# RHIFactory::CreateRHIDevice + +```cpp +static RHIDevice* CreateRHIDevice(RHIType type); +``` + +根据枚举类型创建 RHI 设备。 + +**参数:** +- `type` - 后端类型枚举值 + +**返回:** 新创建的设备指针,失败返回 `nullptr` + +**复杂度:** O(1) + +**示例:** + +```cpp +RHIDevice* device = RHIFactory::CreateRHIDevice(RHIType::D3D12); +if (device) { + device->Initialize(desc); +} +``` + +## 相关文档 + +- [RHIFactory 总览](factory.md) - 返回类总览 +- [RHIType](../enums/enums.md) - 枚举类型 diff --git a/docs/api/rhi/factory/factory.md b/docs/api/rhi/factory/factory.md new file mode 100644 index 0000000..8b0729d --- /dev/null +++ b/docs/api/rhi/factory/factory.md @@ -0,0 +1,47 @@ +# RHIFactory + +**命名空间**: `XCEngine::RHI` + +**类型**: `class` (static) + +**描述**: RHI 设备工厂,用于创建不同图形 API 后端的渲染设备。 + +## 概述 + +`RHIFactory` 是静态工厂类,提供统一的接口来创建不同后端的 `RHIDevice` 实例。通过 `RHIType` 枚举指定要创建的后端类型。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`CreateRHIDevice(RHIType)`](create-rhi-device-type.md) | 使用枚举类型创建 RHI 设备 | +| [`CreateRHIDevice(std::string)`](create-rhi-device-string.md) | 使用字符串创建 RHI 设备 | + +## 类型映射 + +| RHIType | typeName 参数值 | +|----------|-----------------| +| `RHIType::D3D12` | `"D3D12"` | +| `RHIType::OpenGL` | `"OpenGL"` | +| `RHIType::Vulkan` | `"Vulkan"` | +| `RHIType::Metal` | `"Metal"` | + +## 使用示例 + +```cpp +// 方法1:使用枚举创建 +RHIDevice* d3d12Device = RHIFactory::CreateRHIDevice(RHIType::D3D12); + +// 方法2:使用字符串创建 +RHIDevice* glDevice = RHIFactory::CreateRHIDevice("OpenGL"); + +// 方法3:根据配置选择 +std::string backend = "D3D12"; +RHIDevice* device = RHIFactory::CreateRHIDevice(backend); +``` + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHIDevice](../device/device.md) - 渲染设备 +- [RHIEnums](../enums/enums.md) - RHIType 枚举定义 diff --git a/docs/api/rhi/fence/fence.md b/docs/api/rhi/fence/fence.md new file mode 100644 index 0000000..cf7592e --- /dev/null +++ b/docs/api/rhi/fence/fence.md @@ -0,0 +1,34 @@ +# RHIFence + +**命名空间**: `XCEngine::RHI` + +**类型**: `class` (abstract) + +**描述**: GPU 同步栅栏抽象接口,用于 GPU/CPU 同步和跨队列同步。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Shutdown`](shutdown.md) | 关闭并释放资源 | +| [`Signal`](signal.md) | 信号栅栏 | +| [`Wait`](wait.md) | 等待栅栏 | +| [`GetCompletedValue`](get-completed-value.md) | 获取完成值 | +| [`IsSignaled`](is-signaled.md) | 检查是否已信号 | +| [`GetNativeHandle`](get-native-handle.md) | 获取原生句柄 | + +## 使用示例 + +```cpp +FenceDesc desc; +desc.initialValue = 0; +RHIFence* fence = device->CreateFence(desc); + +commandQueue->Signal(fence, 1); +fence->Wait(1); +``` + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHICommandQueue](../command-queue/command-queue.md) - 命令队列 diff --git a/docs/api/rhi/fence/get-completed-value.md b/docs/api/rhi/fence/get-completed-value.md new file mode 100644 index 0000000..7d83dc9 --- /dev/null +++ b/docs/api/rhi/fence/get-completed-value.md @@ -0,0 +1,19 @@ +# RHIFence::GetCompletedValue + +```cpp +virtual uint64_t GetCompletedValue() const = 0; +``` + +获取已完成信号值。 + +**返回:** 已完成的信号值 + +**示例:** + +```cpp +uint64_t value = fence->GetCompletedValue(); +``` + +## 相关文档 + +- [RHIFence 总览](fence.md) - 返回类总览 diff --git a/docs/api/rhi/fence/get-native-handle.md b/docs/api/rhi/fence/get-native-handle.md new file mode 100644 index 0000000..c472246 --- /dev/null +++ b/docs/api/rhi/fence/get-native-handle.md @@ -0,0 +1,15 @@ +# RHIFence::GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 + +**返回:** 原生栅栏句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIFence 总览](fence.md) - 返回类总览 diff --git a/docs/api/rhi/fence/is-signaled.md b/docs/api/rhi/fence/is-signaled.md new file mode 100644 index 0000000..b595f56 --- /dev/null +++ b/docs/api/rhi/fence/is-signaled.md @@ -0,0 +1,21 @@ +# RHIFence::IsSignaled + +```cpp +virtual bool IsSignaled() const = 0; +``` + +检查栅栏是否被信号触发。 + +**返回:** 如果栅栏已被信号触发返回 true + +**示例:** + +```cpp +if (fence->IsSignaled()) { + // 栅栏已完成 +} +``` + +## 相关文档 + +- [RHIFence 总览](fence.md) - 返回类总览 diff --git a/docs/api/rhi/fence/methods.md b/docs/api/rhi/fence/methods.md new file mode 100644 index 0000000..8b715be --- /dev/null +++ b/docs/api/rhi/fence/methods.md @@ -0,0 +1,50 @@ +# RHIFence 方法 + +## Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +释放栅栏资源。 + +## Signal + +```cpp +virtual void Signal() = 0; +virtual void Signal(uint64_t value) = 0; +``` + +信号通知(值为 1)或指定值。 + +## Wait + +```cpp +virtual void Wait(uint64_t value) = 0; +``` + +等待指定值。 + +## GetCompletedValue + +```cpp +virtual uint64_t GetCompletedValue() const = 0; +``` + +获取已完成的值。 + +## IsSignaled + +```cpp +virtual bool IsSignaled() const = 0; +``` + +检查是否已信号通知。 + +## GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 diff --git a/docs/api/rhi/fence/shutdown.md b/docs/api/rhi/fence/shutdown.md new file mode 100644 index 0000000..9b2477c --- /dev/null +++ b/docs/api/rhi/fence/shutdown.md @@ -0,0 +1,13 @@ +# RHIFence::Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +释放栅栏资源。 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIFence 总览](fence.md) - 返回类总览 diff --git a/docs/api/rhi/fence/signal.md b/docs/api/rhi/fence/signal.md new file mode 100644 index 0000000..2319c42 --- /dev/null +++ b/docs/api/rhi/fence/signal.md @@ -0,0 +1,22 @@ +# RHIFence::Signal + +```cpp +virtual void Signal() = 0; +virtual void Signal(uint64_t value) = 0; +``` + +向栅栏发送信号。 + +**参数:** +- `value` - 信号值(重载版本) + +**示例:** + +```cpp +fence->Signal(); +fence->Signal(1); +``` + +## 相关文档 + +- [RHIFence 总览](fence.md) - 返回类总览 diff --git a/docs/api/rhi/fence/wait.md b/docs/api/rhi/fence/wait.md new file mode 100644 index 0000000..b7d6d04 --- /dev/null +++ b/docs/api/rhi/fence/wait.md @@ -0,0 +1,20 @@ +# RHIFence::Wait + +```cpp +virtual void Wait(uint64_t value) = 0; +``` + +等待栅栏达到指定值。 + +**参数:** +- `value` - 要等待的值 + +**示例:** + +```cpp +fence->Wait(1); +``` + +## 相关文档 + +- [RHIFence 总览](fence.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/README.md b/docs/api/rhi/opengl/README.md new file mode 100644 index 0000000..a2e4a91 --- /dev/null +++ b/docs/api/rhi/opengl/README.md @@ -0,0 +1,26 @@ +# OpenGL 后端组件 + +OpenGL 后端已创建以下组件文件夹和文档: + +- `device/` - OpenGLDevice +- `buffer/` - OpenGLBuffer +- `texture/` - OpenGLTexture +- `command-list/` - OpenGLCommandList +- `command-queue/` - OpenGLCommandQueue +- `swap-chain/` - OpenGLSwapChain +- `fence/` - OpenGLFence +- `shader/` - OpenGLShader +- `pipeline-state/` - OpenGLPipelineState +- `sampler/` - OpenGLSampler +- `vertex-array/` - OpenGLVertexArray +- `render-target-view/` - OpenGLRenderTargetView +- `depth-stencil-view/` - OpenGLDepthStencilView + +每个组件文件夹包含: +- `{component}.md` - 类总览 +- `methods.md` - 方法详细文档 + +## 相关文档 + +- [OpenGL 后端总览](overview.md) +- [RHI 抽象层](overview.md) diff --git a/docs/api/rhi/opengl/buffer/bind-base.md b/docs/api/rhi/opengl/buffer/bind-base.md new file mode 100644 index 0000000..6baa012 --- /dev/null +++ b/docs/api/rhi/opengl/buffer/bind-base.md @@ -0,0 +1,21 @@ +# OpenGLBuffer::BindBase + +```cpp +void BindBase(unsigned int target, unsigned int index) const +``` + +将缓冲区绑定到固定的 binding point。 + +**参数:** +- `target` - OpenGL target (如 GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER) +- `index` - binding point 索引 + +**示例:** + +```cpp +buffer.BindBase(GL_UNIFORM_BUFFER, 0); +``` + +## 相关文档 + +- [OpenGLBuffer](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/buffer/bind.md b/docs/api/rhi/opengl/buffer/bind.md new file mode 100644 index 0000000..8305ff0 --- /dev/null +++ b/docs/api/rhi/opengl/buffer/bind.md @@ -0,0 +1,17 @@ +# OpenGLBuffer::Bind + +```cpp +void Bind() const; +``` + +绑定缓冲区到 OpenGL 目标。 + +**示例:** + +```cpp +buffer.Bind(); +``` + +## 相关文档 + +- [OpenGLBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/buffer/buffer.md b/docs/api/rhi/opengl/buffer/buffer.md new file mode 100644 index 0000000..7dc0134 --- /dev/null +++ b/docs/api/rhi/opengl/buffer/buffer.md @@ -0,0 +1,38 @@ +# OpenGLBuffer + +**命名空间**: `XCEngine::RHI` + +**描述**: OpenGL 缓冲区的实现,继承自 `RHIBuffer`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](initialize.md) | 初始化缓冲区 | +| [`InitializeVertexBuffer`](initialize-vertex-buffer.md) | 初始化顶点缓冲 | +| [`InitializeIndexBuffer`](initialize-index-buffer.md) | 初始化索引缓冲 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭缓冲区 | +| [`Bind`](bind.md) | 绑定缓冲区 | +| [`Unbind`](unbind.md) | 解绑缓冲区 | +| [`BindBase`](bind-base.md) | 绑定到基准点 | +| [`Map`](../../buffer/map.md) | 映射缓冲区 | +| [`Unmap`](../../buffer/unmap.md) | 取消映射 | +| [`SetData`](../../buffer/set-data.md) | 设置数据 | +| [`GetID`](get-id.md) | 获取 OpenGL 缓冲 ID | +| [`GetSize`](../../buffer/get-size.md) | 获取缓冲区大小 | +| [`GetType`](get-type.md) | 获取缓冲区类型 | +| [`IsDynamic`](is-dynamic.md) | 检查是否动态 | +| [`GetBufferType`](../../buffer/get-buffer-type.md) | 获取缓冲区类型 | +| [`SetBufferType`](../../buffer/set-buffer-type.md) | 设置缓冲区类型 | +| [`GetStride`](../../buffer/get-stride.md) | 获取步长 | +| [`SetStride`](../../buffer/set-stride.md) | 设置步长 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | +| [`GetState`](../../buffer/get-state.md) | 获取资源状态 | +| [`SetState`](../../buffer/set-state.md) | 设置资源状态 | +| [`GetName`](../../buffer/get-name.md) | 获取资源名称 | +| [`SetName`](../../buffer/set-name.md) | 设置资源名称 | + +## 相关文档 + +- [OpenGL 后端总览](../overview.md) +- [RHIBuffer](../../buffer/buffer.md) - 抽象缓冲区接口 diff --git a/docs/api/rhi/opengl/buffer/get-id.md b/docs/api/rhi/opengl/buffer/get-id.md new file mode 100644 index 0000000..76db615 --- /dev/null +++ b/docs/api/rhi/opengl/buffer/get-id.md @@ -0,0 +1,20 @@ +# OpenGLBuffer::GetID + +```cpp +unsigned int GetID() const +``` + +获取 OpenGL buffer 的 GLuint ID。 + +**返回:** OpenGL buffer ID + +**示例:** + +```cpp +unsigned int id = buffer.GetID(); +glBindBuffer(GL_ARRAY_BUFFER, id); +``` + +## 相关文档 + +- [OpenGLBuffer](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/buffer/get-type.md b/docs/api/rhi/opengl/buffer/get-type.md new file mode 100644 index 0000000..feb3bcc --- /dev/null +++ b/docs/api/rhi/opengl/buffer/get-type.md @@ -0,0 +1,19 @@ +# OpenGLBuffer::GetType + +```cpp +OpenGLBufferType GetType() const; +``` + +获取缓冲区类型。 + +**返回:** OpenGL 缓冲区类型 + +**示例:** + +```cpp +OpenGLBufferType type = buffer.GetType(); +``` + +## 相关文档 + +- [OpenGLBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/buffer/initialize-index-buffer.md b/docs/api/rhi/opengl/buffer/initialize-index-buffer.md new file mode 100644 index 0000000..bc23db6 --- /dev/null +++ b/docs/api/rhi/opengl/buffer/initialize-index-buffer.md @@ -0,0 +1,25 @@ +# OpenGLBuffer::InitializeIndexBuffer + +```cpp +bool InitializeIndexBuffer(const void* data, size_t size) +``` + +初始化索引缓冲区。 + +**参数:** +- `data` - 索引数据指针 +- `size` - 数据大小(字节) + +**返回:** 成功返回 true + +**示例:** + +```cpp +uint32_t indices[] = { 0, 1, 2 }; +OpenGLBuffer buffer; +buffer.InitializeIndexBuffer(indices, sizeof(indices)); +``` + +## 相关文档 + +- [OpenGLBuffer](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/buffer/initialize-vertex-buffer.md b/docs/api/rhi/opengl/buffer/initialize-vertex-buffer.md new file mode 100644 index 0000000..e216d9e --- /dev/null +++ b/docs/api/rhi/opengl/buffer/initialize-vertex-buffer.md @@ -0,0 +1,25 @@ +# OpenGLBuffer::InitializeVertexBuffer + +```cpp +bool InitializeVertexBuffer(const void* data, size_t size) +``` + +初始化顶点缓冲区。 + +**参数:** +- `data` - 顶点数据指针 +- `size` - 数据大小(字节) + +**返回:** 成功返回 true + +**示例:** + +```cpp +float vertices[] = { 0.0f, 0.5f, 0.0f }; +OpenGLBuffer buffer; +buffer.InitializeVertexBuffer(vertices, sizeof(vertices)); +``` + +## 相关文档 + +- [OpenGLBuffer](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/buffer/initialize.md b/docs/api/rhi/opengl/buffer/initialize.md new file mode 100644 index 0000000..9ccb8ac --- /dev/null +++ b/docs/api/rhi/opengl/buffer/initialize.md @@ -0,0 +1,26 @@ +# OpenGLBuffer::Initialize + +```cpp +bool Initialize(OpenGLBufferType type, size_t size, const void* data = nullptr, bool dynamic = false); +``` + +初始化 OpenGL 缓冲区。 + +**参数:** +- `type` - 缓冲区类型 +- `size` - 缓冲区大小(字节) +- `data` - 初始数据指针(可选) +- `dynamic` - 是否为动态缓冲区 + +**返回:** 成功返回 true + +**示例:** + +```cpp +OpenGLBuffer buffer; +buffer.Initialize(OpenGLBufferType::Vertex, sizeof(vertices), vertices); +``` + +## 相关文档 + +- [OpenGLBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/buffer/is-dynamic.md b/docs/api/rhi/opengl/buffer/is-dynamic.md new file mode 100644 index 0000000..40e892d --- /dev/null +++ b/docs/api/rhi/opengl/buffer/is-dynamic.md @@ -0,0 +1,24 @@ +# OpenGLBuffer::IsDynamic + +```cpp +bool IsDynamic() const +``` + +判断缓冲区是否为动态缓冲区。 + +**返回:** 如果是动态缓冲区返回 true + +**示例:** + +```cpp +if (buffer.IsDynamic()) { + // 动态缓冲区可以直接 Map/Unmap + void* data = buffer.Map(); + // ... + buffer.Unmap(); +} +``` + +## 相关文档 + +- [OpenGLBuffer](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/buffer/unbind.md b/docs/api/rhi/opengl/buffer/unbind.md new file mode 100644 index 0000000..63209b5 --- /dev/null +++ b/docs/api/rhi/opengl/buffer/unbind.md @@ -0,0 +1,17 @@ +# OpenGLBuffer::Unbind + +```cpp +void Unbind() const; +``` + +解除绑定缓冲区。 + +**示例:** + +```cpp +buffer.Unbind(); +``` + +## 相关文档 + +- [OpenGLBuffer 总览](buffer.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/clear-color.md b/docs/api/rhi/opengl/command-list/clear-color.md new file mode 100644 index 0000000..6c7638f --- /dev/null +++ b/docs/api/rhi/opengl/command-list/clear-color.md @@ -0,0 +1,23 @@ +# OpenGLCommandList::ClearColor + +```cpp +void ClearColor(float r, float g, float b, float a) +``` + +清除颜色缓冲区。 + +**参数:** +- `r` - 红色分量 (0.0-1.0) +- `g` - 绿色分量 (0.0-1.0) +- `b` - 蓝色分量 (0.0-1.0) +- `a` - 透明度分量 (0.0-1.0) + +**示例:** + +```cpp +commandList->ClearColor(0.0f, 0.0f, 0.0f, 1.0f); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/clear-depth-stencil.md b/docs/api/rhi/opengl/command-list/clear-depth-stencil.md new file mode 100644 index 0000000..b81f0fa --- /dev/null +++ b/docs/api/rhi/opengl/command-list/clear-depth-stencil.md @@ -0,0 +1,22 @@ +# OpenGLCommandList::ClearDepthStencil + +```cpp +void ClearDepthStencil(void* depthStencil, float depth, uint8_t stencil) +``` + +清除深度模板目标。 + +**参数:** +- `depthStencil` - 深度模板目标指针 +- `depth` - 深度值 +- `stencil` - 模板值 + +**示例:** + +```cpp +commandList->ClearDepthStencil(depthStencil, 1.0f, 0); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/clear-depth.md b/docs/api/rhi/opengl/command-list/clear-depth.md new file mode 100644 index 0000000..66bea50 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/clear-depth.md @@ -0,0 +1,20 @@ +# OpenGLCommandList::ClearDepth + +```cpp +void ClearDepth(float depth) +``` + +清除深度缓冲区。 + +**参数:** +- `depth` - 深度值 (0.0-1.0) + +**示例:** + +```cpp +commandList->ClearDepth(1.0f); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/clear-render-target.md b/docs/api/rhi/opengl/command-list/clear-render-target.md new file mode 100644 index 0000000..e3c1063 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/clear-render-target.md @@ -0,0 +1,22 @@ +# OpenGLCommandList::ClearRenderTarget + +```cpp +void ClearRenderTarget(void* renderTarget, const float color[4]) +``` + +清除渲染目标。 + +**参数:** +- `renderTarget` - 渲染目标指针 +- `color` - 清除颜色 [r, g, b, a] + +**示例:** + +```cpp +float color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; +commandList->ClearRenderTarget(renderTarget, color); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/clear-stencil.md b/docs/api/rhi/opengl/command-list/clear-stencil.md new file mode 100644 index 0000000..5a26581 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/clear-stencil.md @@ -0,0 +1,20 @@ +# OpenGLCommandList::ClearStencil + +```cpp +void ClearStencil(int stencil) +``` + +清除模板缓冲区。 + +**参数:** +- `stencil` - 模板值 + +**示例:** + +```cpp +commandList->ClearStencil(0); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/clear.md b/docs/api/rhi/opengl/command-list/clear.md new file mode 100644 index 0000000..3eedf54 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/clear.md @@ -0,0 +1,24 @@ +# OpenGLCommandList::Clear + +```cpp +void Clear(float r, float g, float b, float a, unsigned int buffers); +``` + +清除缓冲区。 + +**参数:** +- `r` - 红色分量 +- `g` - 绿色分量 +- `b` - 蓝色分量 +- `a` - Alpha 分量 +- `buffers` - 要清除的缓冲区标志 + +**示例:** + +```cpp +commandList->Clear(0.0f, 0.0f, 0.0f, 1.0f, Color | Depth); +``` + +## 相关文档 + +- [OpenGLCommandList 总览](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/command-list.md b/docs/api/rhi/opengl/command-list/command-list.md new file mode 100644 index 0000000..56f8243 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/command-list.md @@ -0,0 +1,44 @@ +# OpenGLCommandList + +**命名空间**: `XCEngine::RHI` + +**描述**: OpenGL 命令列表实现,继承自 `RHICommandList`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭命令列表 | +| [`Reset`](../../command-list/reset.md) | 重置命令列表 | +| [`Close`](../../command-list/close.md) | 关闭命令列表 | +| [`Clear`](clear.md) | 清除 | +| [`ClearColor`](clear-color.md) | 清除颜色 | +| [`ClearDepth`](clear-depth.md) | 清除深度 | +| [`ClearStencil`](clear-stencil.md) | 清除模板 | +| [`ClearDepthStencil`](clear-depth-stencil.md) | 清除深度模板 | +| [`SetPipelineState`](set-pipeline-state.md) | 设置管线状态 | +| [`SetVertexBuffer`](set-vertex-buffer.md) | 设置顶点缓冲 | +| [`SetVertexBuffers`](set-vertex-buffers.md) | 设置多个顶点缓冲 | +| [`SetIndexBuffer`](set-index-buffer.md) | 设置索引缓冲 | +| [`TransitionBarrier`](transition-barrier.md) | 资源状态转换 | +| [`SetPrimitiveTopology`](set-primitive-topology.md) | 设置图元拓扑 | +| [`SetViewport`](set-viewport.md) | 设置视口 | +| [`SetViewports`](set-viewports.md) | 设置多个视口 | +| [`SetScissorRect`](set-scissor-rect.md) | 设置裁剪矩形 | +| [`SetScissorRects`](set-scissor-rects.md) | 设置多个裁剪矩形 | +| [`SetRenderTargets`](set-render-targets.md) | 设置渲染目标 | +| [`SetDepthStencilState`](set-depth-stencil-state.md) | 设置深度模板状态 | +| [`SetStencilRef`](set-stencil-ref.md) | 设置模板引用值 | +| [`SetBlendState`](set-blend-state.md) | 设置混合状态 | +| [`SetBlendFactor`](set-blend-factor.md) | 设置混合因子 | +| [`ClearRenderTarget`](clear-render-target.md) | 清除渲染目标 | +| [`Draw`](draw.md) | 绘制 | +| [`DrawIndexed`](draw-indexed.md) | 索引绘制 | +| [`Dispatch`](dispatch.md) | 分发计算任务 | +| [`CopyResource`](copy-resource.md) | 复制资源 | +| [`OpenGLMethods`](opengl-methods.md) | OpenGL 特有方法 | + +## 相关文档 + +- [OpenGL 后端总览](../overview.md) +- [RHICommandList](../../command-list/command-list.md) - 抽象命令列表接口 diff --git a/docs/api/rhi/opengl/command-list/copy-resource.md b/docs/api/rhi/opengl/command-list/copy-resource.md new file mode 100644 index 0000000..f06886c --- /dev/null +++ b/docs/api/rhi/opengl/command-list/copy-resource.md @@ -0,0 +1,21 @@ +# OpenGLCommandList::CopyResource + +```cpp +void CopyResource(void* dst, void* src) +``` + +复制资源。 + +**参数:** +- `dst` - 目标资源指针 +- `src` - 源资源指针 + +**示例:** + +```cpp +commandList->CopyResource(dstTexture, srcTexture); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/dispatch.md b/docs/api/rhi/opengl/command-list/dispatch.md new file mode 100644 index 0000000..b3b80aa --- /dev/null +++ b/docs/api/rhi/opengl/command-list/dispatch.md @@ -0,0 +1,22 @@ +# OpenGLCommandList::Dispatch + +```cpp +void Dispatch(uint32_t x, uint32_t y, uint32_t z) +``` + +分发计算着色器。 + +**参数:** +- `x` - X 方向线程组数量 +- `y` - Y 方向线程组数量 +- `z` - Z 方向线程组数量 + +**示例:** + +```cpp +commandList->Dispatch(8, 8, 1); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/draw-indexed.md b/docs/api/rhi/opengl/command-list/draw-indexed.md new file mode 100644 index 0000000..7f4f691 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/draw-indexed.md @@ -0,0 +1,24 @@ +# OpenGLCommandList::DrawIndexed + +```cpp +void DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) +``` + +绘制索引图元。 + +**参数:** +- `indexCount` - 索引数量 +- `instanceCount` - 实例数量 +- `startIndex` - 起始索引 +- `baseVertex` - 基础顶点 +- `startInstance` - 起始实例 + +**示例:** + +```cpp +commandList->DrawIndexed(6, 1, 0, 0, 0); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/draw.md b/docs/api/rhi/opengl/command-list/draw.md new file mode 100644 index 0000000..bbdf938 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/draw.md @@ -0,0 +1,23 @@ +# OpenGLCommandList::Draw + +```cpp +void Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertex, uint32_t startInstance) +``` + +绘制非索引图元。 + +**参数:** +- `vertexCount` - 顶点数量 +- `instanceCount` - 实例数量 +- `startVertex` - 起始顶点 +- `startInstance` - 起始实例 + +**示例:** + +```cpp +commandList->Draw(3, 1, 0, 0); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/opengl-methods.md b/docs/api/rhi/opengl/command-list/opengl-methods.md new file mode 100644 index 0000000..e6c1327 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/opengl-methods.md @@ -0,0 +1,545 @@ +# OpenGLCommandList - OpenGL 特有方法 + +以下是 `OpenGLCommandList` 中 OpenGL 特有的底层逃逸方法。这些方法不存在于 RHI 抽象接口中,用于需要直接操作 OpenGL 状态的高级场景。 + +## 顶点缓冲区(OpenGL 逃逸) + +### SetVertexBuffer (GL uint) + +```cpp +void SetVertexBuffer(unsigned int buffer, size_t offset, size_t stride) +``` + +直接使用 OpenGL buffer ID 设置顶点缓冲区。 + +### SetVertexBuffers (GL uint) + +```cpp +void SetVertexBuffers(unsigned int startSlot, unsigned int count, const unsigned int* buffers, const size_t* offsets, const size_t* strides) +``` + +批量设置顶点缓冲区。 + +### SetIndexBuffer (GL uint) + +```cpp +void SetIndexBuffer(unsigned int buffer, unsigned int type) +void SetIndexBuffer(unsigned int buffer, unsigned int type, size_t offset) +``` + +直接设置索引缓冲区。 + +## 顶点数组 + +### BindVertexArray + +```cpp +void BindVertexArray(unsigned int vao) +void BindVertexArray(unsigned int vao, unsigned int indexBuffer, unsigned int indexType) +``` + +绑定 VAO,可同时设置索引缓冲区。 + +### UseShader + +```cpp +void UseShader(unsigned int program) +``` + +使用 shader program。 + +## 视口与裁剪 + +### SetViewport (int) + +```cpp +void SetViewport(int x, int y, int width, int height) +``` + +使用整数参数设置视口。 + +### SetViewport (float) + +```cpp +void SetViewport(float x, float y, float width, float height, float minDepth, float maxDepth) +``` + +使用浮点参数设置视口。 + +### SetViewports + +```cpp +void SetViewports(unsigned int count, const float* viewports) +``` + +批量设置视口(6 个浮点值 per viewport: x, y, width, height, minDepth, maxDepth)。 + +### SetScissor + +```cpp +void SetScissor(int x, int y, int width, int height) +``` + +设置裁剪矩形。 + +### SetScissorRects + +```cpp +void SetScissorRects(unsigned int count, const int* rects) +``` + +批量设置裁剪矩形(4 个整数值 per rect: x, y, width, height)。 + +### EnableScissorTest + +```cpp +void EnableScissorTest(bool enable) +``` + +启用/禁用裁剪测试。 + +## 深度测试 + +### EnableDepthTest + +```cpp +void EnableDepthTest(bool enable) +``` + +启用/禁用深度测试。 + +### EnableDepthWrite + +```cpp +void EnableDepthWrite(bool enable) +``` + +启用/禁用深度写入。 + +### SetDepthFunc + +```cpp +void SetDepthFunc(unsigned int func) +``` + +设置深度比较函数(GL_NEVER, GL_LESS, GL_EQUAL, etc.)。 + +## 模板测试 + +### EnableStencilTest + +```cpp +void EnableStencilTest(bool enable) +``` + +启用/禁用模板测试。 + +### SetStencilFunc + +```cpp +void SetStencilFunc(unsigned int func, int ref, unsigned int mask) +``` + +设置模板测试函数。 + +### SetStencilOp + +```cpp +void SetStencilOp(unsigned int fail, unsigned int zfail, unsigned int zpass) +``` + +设置模板操作。 + +## 混合 + +### EnableBlending + +```cpp +void EnableBlending(bool enable) +``` + +启用/禁用混合。 + +### SetBlendFunc + +```cpp +void SetBlendFunc(unsigned int src, unsigned int dst) +``` + +设置混合函数。 + +### SetBlendFuncSeparate + +```cpp +void SetBlendFuncSeparate(unsigned int srcRGB, unsigned int dstRGB, unsigned int srcAlpha, unsigned int dstAlpha) +``` + +分别设置 RGB 和 Alpha 的混合函数。 + +### SetBlendEquation + +```cpp +void SetBlendEquation(unsigned int mode) +``` + +设置混合方程。 + +### SetBlendColor + +```cpp +void SetBlendColor(float r, float g, float b, float a) +``` + +设置混合因子颜色。 + +## 光栅化 + +### EnableCulling + +```cpp +void EnableCulling(bool enable) +``` + +启用/禁用面剔除。 + +### SetCullFace + +```cpp +void SetCullFace(unsigned int face) +``` + +设置剔除面(GL_FRONT, GL_BACK, GL_FRONT_AND_BACK)。 + +### SetFrontFace + +```cpp +void SetFrontFace(unsigned int face) +``` + +设置正面方向(GL_CW, GL_CCW)。 + +### SetPolygonMode + +```cpp +void SetPolygonMode(unsigned int mode) +``` + +设置多边形模式(GL_POINT, GL_LINE, GL_FILL)。 + +### SetPolygonOffset + +```cpp +void SetPolygonOffset(float factor, float units) +``` + +设置多边形偏移。 + +### SetPrimitiveType + +```cpp +void SetPrimitiveType(PrimitiveType type) +``` + +设置图元类型。 + +## 绘制(OpenGL 类型) + +### Draw (PrimitiveType) + +```cpp +void Draw(PrimitiveType type, unsigned int vertexCount, unsigned int startVertex) +``` + +绘制非索引图元。 + +### DrawInstanced + +```cpp +void DrawInstanced(PrimitiveType type, unsigned int vertexCount, unsigned int instanceCount, unsigned int startVertex, unsigned int startInstance) +``` + +实例化绘制。 + +### DrawIndexed (PrimitiveType) + +```cpp +void DrawIndexed(PrimitiveType type, unsigned int indexCount, unsigned int startIndex, int baseVertex) +``` + +绘制索引图元。 + +### DrawIndexedInstanced + +```cpp +void DrawIndexedInstanced(PrimitiveType type, unsigned int indexCount, unsigned int instanceCount, unsigned int startIndex, int baseVertex, unsigned int startInstance) +``` + +实例化索引绘制。 + +### DrawIndirect + +```cpp +void DrawIndirect(PrimitiveType type, unsigned int buffer, size_t offset, unsigned int drawCount, unsigned int stride) +``` + +间接绘制。 + +### DrawIndexedIndirect + +```cpp +void DrawIndexedIndirect(PrimitiveType type, unsigned int buffer, size_t offset, unsigned int drawCount, unsigned int stride) +``` + +间接索引绘制。 + +### MultiDrawArrays + +```cpp +void MultiDrawArrays(PrimitiveType type, const int* first, const int* count, unsigned int drawCount) +``` + +多重绘制。 + +### MultiDrawElements + +```cpp +void MultiDrawElements(PrimitiveType type, const int* count, unsigned int type_, const void* const* indices, unsigned int drawCount) +``` + +多重索引绘制。 + +## 计算着色器 + +### DispatchIndirect + +```cpp +void DispatchIndirect(unsigned int buffer, size_t offset) +``` + +间接分发计算着色器。 + +### DispatchCompute + +```cpp +void DispatchCompute(unsigned int x, unsigned int y, unsigned int z, unsigned int groupX, unsigned int groupY, unsigned int groupZ) +``` + +分发计算着色器(带参数)。 + +## 内存屏障 + +### MemoryBarrier + +```cpp +void MemoryBarrier(unsigned int barriers) +``` + +设置内存屏障。 + +### TextureBarrier + +```cpp +void TextureBarrier() +``` + +纹理屏障。 + +## 纹理绑定 + +### BindTexture + +```cpp +void BindTexture(unsigned int target, unsigned int unit, unsigned int texture) +``` + +绑定纹理到纹理单元。 + +### BindTextures + +```cpp +void BindTextures(unsigned int first, unsigned int count, const unsigned int* textures) +``` + +批量绑定纹理。 + +### BindSampler + +```cpp +void BindSampler(unsigned int unit, unsigned int sampler) +``` + +绑定采样器。 + +### BindSamplers + +```cpp +void BindSamplers(unsigned int first, unsigned int count, const unsigned int* samplers) +``` + +批量绑定采样器。 + +### BindImageTexture + +```cpp +void BindImageTexture(unsigned int unit, unsigned int texture, int level, bool layered, int layer, unsigned int access, unsigned int format) +``` + +绑定为 image texture。 + +## 缓冲区绑定 + +### BindBufferBase + +```cpp +void BindBufferBase(unsigned int target, unsigned int index, unsigned int buffer) +``` + +绑定到固定 binding point。 + +### BindBufferRange + +```cpp +void BindBufferRange(unsigned int target, unsigned int index, unsigned int buffer, size_t offset, size_t size) +``` + +绑定到范围 binding point。 + +## OpenGL 状态 + +### Enable / Disable + +```cpp +void Enable(unsigned int cap) +void Disable(unsigned int cap) +void Enablei(unsigned int cap, unsigned int index) +void Disablei(unsigned int cap, unsigned int index) +``` + +启用/禁用 GL capability。 + +## Uniform 设置 + +### SetUniform1i / SetUniform1f + +```cpp +void SetUniform1i(int location, int v) +void SetUniform1f(int location, float v) +``` + +### SetUniform2f + +```cpp +void SetUniform2f(int location, float x, float y) +``` + +### SetUniform3f + +```cpp +void SetUniform3f(int location, float x, float y, float z) +``` + +### SetUniform4f + +```cpp +void SetUniform4f(int location, float x, float y, float z, float w) +``` + +### SetUniform1fv / SetUniform2fv / SetUniform3fv / SetUniform4fv + +```cpp +void SetUniform1fv(int location, int count, const float* v) +void SetUniform2fv(int location, int count, const float* v) +void SetUniform3fv(int location, int count, const float* v) +void SetUniform4fv(int location, int count, const float* v) +``` + +### SetUniformMatrix4fv + +```cpp +void SetUniformMatrix4fv(int location, int count, bool transpose, const float* v) +``` + +## Shader 程序 + +### UseProgram + +```cpp +void UseProgram(unsigned int program) +``` + +使用 program。 + +### BindFragDataLocation + +```cpp +void BindFragDataLocation(unsigned int program, unsigned int colorNumber, const char* name) +void BindFragDataLocationIndexed(unsigned int program, unsigned int colorNumber, unsigned int index, const char* name) +``` + +设置颜色输出绑定。 + +## 查询 + +### BeginQuery / EndQuery + +```cpp +void BeginQuery(unsigned int target, unsigned int id) +void EndQuery(unsigned int target) +``` + +开始/结束查询。 + +### GetQueryObjectiv / GetQueryObjectuiv + +```cpp +void GetQueryObjectiv(unsigned int id, unsigned int pname, int* params) +void GetQueryObjectuiv(unsigned int id, unsigned int pname, unsigned int* params) +``` + +获取查询结果。 + +## Framebuffer 操作 + +### ReadPixels + +```cpp +void ReadPixels(int x, int y, int width, int height, unsigned int format, unsigned int type, void* data) +``` + +读取像素。 + +### BlitFramebuffer + +```cpp +void BlitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, unsigned int mask, unsigned int filter) +``` + +Blit 帧缓冲区。 + +### CopyImageSubData + +```cpp +void CopyImageSubData(unsigned int srcName, unsigned int srcTarget, int srcLevel, int srcX, int srcY, int srcZ, unsigned int dstName, unsigned int dstTarget, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth) +``` + +复制图像子数据。 + +### InvalidateFramebuffer + +```cpp +void InvalidateFramebuffer(unsigned int target, unsigned int count, const unsigned int* attachments) +void InvalidateSubFramebuffer(unsigned int target, unsigned int count, const unsigned int* attachments, int x, int y, int width, int height) +``` + +使帧缓冲区失效。 + +## 调试 + +### PushDebugGroup / PopDebugGroup + +```cpp +void PushDebugGroup(unsigned int source, unsigned int id, int length, const char* message) +void PopDebugGroup() +``` + +推送/弹出调试组。 diff --git a/docs/api/rhi/opengl/command-list/set-blend-factor.md b/docs/api/rhi/opengl/command-list/set-blend-factor.md new file mode 100644 index 0000000..27c00f6 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-blend-factor.md @@ -0,0 +1,21 @@ +# OpenGLCommandList::SetBlendFactor + +```cpp +void SetBlendFactor(const float factor[4]) +``` + +设置混合因子。 + +**参数:** +- `factor` - 混合因子数组 [r, g, b, a] + +**示例:** + +```cpp +float factor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; +commandList->SetBlendFactor(factor); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/set-blend-state.md b/docs/api/rhi/opengl/command-list/set-blend-state.md new file mode 100644 index 0000000..cc0daf3 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-blend-state.md @@ -0,0 +1,24 @@ +# OpenGLCommandList::SetBlendState + +```cpp +void SetBlendState(const BlendState& state) +``` + +设置混合状态。 + +**参数:** +- `state` - 混合状态结构 + +**示例:** + +```cpp +BlendState state; +state.enable = true; +state.srcBlend = BlendFunc::SrcAlpha; +state.dstBlend = BlendFunc::InvSrcAlpha; +commandList->SetBlendState(state); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/set-depth-stencil-state.md b/docs/api/rhi/opengl/command-list/set-depth-stencil-state.md new file mode 100644 index 0000000..a7111ad --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-depth-stencil-state.md @@ -0,0 +1,24 @@ +# OpenGLCommandList::SetDepthStencilState + +```cpp +void SetDepthStencilState(const DepthStencilState& state) +``` + +设置深度模板状态。 + +**参数:** +- `state` - 深度模板状态结构 + +**示例:** + +```cpp +DepthStencilState state; +state.depthEnable = true; +state.depthWriteEnable = true; +state.depthFunc = ComparisonFunc::Less; +commandList->SetDepthStencilState(state); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/set-index-buffer.md b/docs/api/rhi/opengl/command-list/set-index-buffer.md new file mode 100644 index 0000000..12fafe2 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-index-buffer.md @@ -0,0 +1,22 @@ +# OpenGLCommandList::SetIndexBuffer + +```cpp +void SetIndexBuffer(void* buffer, uint64_t offset, Format format) +``` + +设置索引缓冲区。 + +**参数:** +- `buffer` - 缓冲区指针 +- `offset` - 数据偏移 +- `format` - 索引格式 + +**示例:** + +```cpp +commandList->SetIndexBuffer(indexBuffer, 0, Format::R32_UINT); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/set-pipeline-state.md b/docs/api/rhi/opengl/command-list/set-pipeline-state.md new file mode 100644 index 0000000..a035992 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-pipeline-state.md @@ -0,0 +1,20 @@ +# OpenGLCommandList::SetPipelineState + +```cpp +void SetPipelineState(void* pipelineState) +``` + +设置渲染管线状态。 + +**参数:** +- `pipelineState` - 管线状态对象指针 + +**示例:** + +```cpp +commandList->SetPipelineState(pipelineState); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/set-primitive-topology.md b/docs/api/rhi/opengl/command-list/set-primitive-topology.md new file mode 100644 index 0000000..8ddb42c --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-primitive-topology.md @@ -0,0 +1,20 @@ +# OpenGLCommandList::SetPrimitiveTopology + +```cpp +void SetPrimitiveTopology(PrimitiveTopology topology) +``` + +设置图元拓扑类型。 + +**参数:** +- `topology` - 图元拓扑类型 + +**示例:** + +```cpp +commandList->SetPrimitiveTopology(PrimitiveTopology::TriangleList); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/set-render-targets.md b/docs/api/rhi/opengl/command-list/set-render-targets.md new file mode 100644 index 0000000..081eb74 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-render-targets.md @@ -0,0 +1,23 @@ +# OpenGLCommandList::SetRenderTargets + +```cpp +void SetRenderTargets(uint32_t count, void** renderTargets, void* depthStencil = nullptr) +``` + +设置渲染目标。 + +**参数:** +- `count` - 渲染目标数量 +- `renderTargets` - 渲染目标指针数组 +- `depthStencil` - 深度模板缓冲区指针(可选) + +**示例:** + +```cpp +void* targets[1] = { colorTarget }; +commandList->SetRenderTargets(1, targets, depthStencil); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/set-scissor-rect.md b/docs/api/rhi/opengl/command-list/set-scissor-rect.md new file mode 100644 index 0000000..4434bba --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-scissor-rect.md @@ -0,0 +1,23 @@ +# OpenGLCommandList::SetScissorRect + +```cpp +void SetScissorRect(const Rect& rect) +``` + +设置裁剪矩形。 + +**参数:** +- `rect` - 裁剪矩形结构 + +**示例:** + +```cpp +Rect rect; +rect.x = 0; rect.y = 0; +rect.width = 800; rect.height = 600; +commandList->SetScissorRect(rect); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/set-scissor-rects.md b/docs/api/rhi/opengl/command-list/set-scissor-rects.md new file mode 100644 index 0000000..d3567b6 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-scissor-rects.md @@ -0,0 +1,22 @@ +# OpenGLCommandList::SetScissorRects + +```cpp +void SetScissorRects(uint32_t count, const Rect* rects) +``` + +批量设置裁剪矩形。 + +**参数:** +- `count` - 裁剪矩形数量 +- `rects` - 裁剪矩形数组指针 + +**示例:** + +```cpp +Rect rects[2] = { ... }; +commandList->SetScissorRects(2, rects); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/set-stencil-ref.md b/docs/api/rhi/opengl/command-list/set-stencil-ref.md new file mode 100644 index 0000000..1227c33 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-stencil-ref.md @@ -0,0 +1,20 @@ +# OpenGLCommandList::SetStencilRef + +```cpp +void SetStencilRef(uint8_t ref) +``` + +设置模板测试参考值。 + +**参数:** +- `ref` - 模板参考值 + +**示例:** + +```cpp +commandList->SetStencilRef(1); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/set-vertex-buffer.md b/docs/api/rhi/opengl/command-list/set-vertex-buffer.md new file mode 100644 index 0000000..8d1bdc0 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-vertex-buffer.md @@ -0,0 +1,23 @@ +# OpenGLCommandList::SetVertexBuffer + +```cpp +void SetVertexBuffer(uint32_t slot, void* buffer, uint64_t offset, uint32_t stride) +``` + +设置单个顶点缓冲区。 + +**参数:** +- `slot` - 顶点缓冲区槽位 +- `buffer` - 缓冲区指针 +- `offset` - 数据偏移 +- `stride` - 顶点跨度 + +**示例:** + +```cpp +commandList->SetVertexBuffer(0, vertexBuffer, 0, sizeof(Vertex)); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/set-vertex-buffers.md b/docs/api/rhi/opengl/command-list/set-vertex-buffers.md new file mode 100644 index 0000000..f5647dd --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-vertex-buffers.md @@ -0,0 +1,24 @@ +# OpenGLCommandList::SetVertexBuffers + +```cpp +void SetVertexBuffers(uint32_t startSlot, uint32_t count, const uint64_t* buffers, const uint64_t* offsets, const uint32_t* strides) +``` + +批量设置顶点缓冲区。 + +**参数:** +- `startSlot` - 起始槽位 +- `count` - 缓冲区数量 +- `buffers` - 缓冲区指针数组 +- `offsets` - 偏移数组 +- `strides` - 跨度数组 + +**示例:** + +```cpp +commandList->SetVertexBuffers(0, 2, buffers, offsets, strides); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/set-viewport.md b/docs/api/rhi/opengl/command-list/set-viewport.md new file mode 100644 index 0000000..85a367c --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-viewport.md @@ -0,0 +1,24 @@ +# OpenGLCommandList::SetViewport + +```cpp +void SetViewport(const Viewport& viewport) +``` + +设置视口。 + +**参数:** +- `viewport` - 视口结构 + +**示例:** + +```cpp +Viewport viewport; +viewport.x = 0; viewport.y = 0; +viewport.width = 800; viewport.height = 600; +viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; +commandList->SetViewport(viewport); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/set-viewports.md b/docs/api/rhi/opengl/command-list/set-viewports.md new file mode 100644 index 0000000..b513ef4 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/set-viewports.md @@ -0,0 +1,22 @@ +# OpenGLCommandList::SetViewports + +```cpp +void SetViewports(uint32_t count, const Viewport* viewports) +``` + +批量设置视口。 + +**参数:** +- `count` - 视口数量 +- `viewports` - 视口数组指针 + +**示例:** + +```cpp +Viewport viewports[2] = { ... }; +commandList->SetViewports(2, viewports); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-list/transition-barrier.md b/docs/api/rhi/opengl/command-list/transition-barrier.md new file mode 100644 index 0000000..0e4dda1 --- /dev/null +++ b/docs/api/rhi/opengl/command-list/transition-barrier.md @@ -0,0 +1,22 @@ +# OpenGLCommandList::TransitionBarrier + +```cpp +void TransitionBarrier(void* resource, ResourceStates stateBefore, ResourceStates stateAfter) +``` + +设置资源状态转换屏障。 + +**参数:** +- `resource` - 资源指针 +- `stateBefore` - 转换前状态 +- `stateAfter` - 转换后状态 + +**示例:** + +```cpp +commandList->TransitionBarrier(texture, ResourceStates::RenderTarget, ResourceStates::Common); +``` + +## 相关文档 + +- [OpenGLCommandList](command-list.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-queue/command-queue.md b/docs/api/rhi/opengl/command-queue/command-queue.md new file mode 100644 index 0000000..2c5f671 --- /dev/null +++ b/docs/api/rhi/opengl/command-queue/command-queue.md @@ -0,0 +1,24 @@ +# OpenGLCommandQueue + +**命名空间**: `XCEngine::RHI` + +**描述**: OpenGL 命令队列实现,继承自 `RHICommandQueue`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭命令队列 | +| [`ExecuteCommandLists`](execute-command-lists.md) | 执行命令列表 | +| [`Signal`](signal.md) | 信号栅栏 | +| [`Wait`](../../../threading/task-group/wait.md) | 等待栅栏 | +| [`GetCompletedValue`](get-completed-value.md) | 获取完成值 | +| [`WaitForIdle`](wait-for-idle.md) | 等待空闲 | +| [`GetType`](../../command-queue/get-type.md) | 获取队列类型 | +| [`GetTimestampFrequency`](get-timestamp-frequency.md) | 获取时间戳频率 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | + +## 相关文档 + +- [OpenGL 后端总览](../overview.md) +- [RHICommandQueue](../../command-queue/command-queue.md) - 抽象命令队列接口 diff --git a/docs/api/rhi/opengl/command-queue/execute-command-lists.md b/docs/api/rhi/opengl/command-queue/execute-command-lists.md new file mode 100644 index 0000000..60ad7d5 --- /dev/null +++ b/docs/api/rhi/opengl/command-queue/execute-command-lists.md @@ -0,0 +1,22 @@ +# OpenGLCommandQueue::ExecuteCommandLists + +```cpp +void ExecuteCommandLists(uint32_t count, void** lists) +``` + +执行命令列表。 + +**参数:** +- `count` - 命令列表数量 +- `lists` - 命令列表指针数组 + +**示例:** + +```cpp +void* lists[] = { commandList }; +commandQueue->ExecuteCommandLists(1, lists); +``` + +## 相关文档 + +- [OpenGLCommandQueue](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-queue/get-completed-value.md b/docs/api/rhi/opengl/command-queue/get-completed-value.md new file mode 100644 index 0000000..d110718 --- /dev/null +++ b/docs/api/rhi/opengl/command-queue/get-completed-value.md @@ -0,0 +1,19 @@ +# OpenGLCommandQueue::GetCompletedValue + +```cpp +uint64_t GetCompletedValue() +``` + +获取已完成的值。 + +**返回:** 已完成的围栏值 + +**示例:** + +```cpp +uint64_t value = commandQueue->GetCompletedValue(); +``` + +## 相关文档 + +- [OpenGLCommandQueue](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-queue/get-timestamp-frequency.md b/docs/api/rhi/opengl/command-queue/get-timestamp-frequency.md new file mode 100644 index 0000000..a21eb79 --- /dev/null +++ b/docs/api/rhi/opengl/command-queue/get-timestamp-frequency.md @@ -0,0 +1,19 @@ +# OpenGLCommandQueue::GetTimestampFrequency + +```cpp +uint64_t GetTimestampFrequency() const +``` + +获取时间戳频率。 + +**返回:** 时间戳频率(Hz) + +**示例:** + +```cpp +uint64_t frequency = commandQueue->GetTimestampFrequency(); +``` + +## 相关文档 + +- [OpenGLCommandQueue](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-queue/signal.md b/docs/api/rhi/opengl/command-queue/signal.md new file mode 100644 index 0000000..282b43a --- /dev/null +++ b/docs/api/rhi/opengl/command-queue/signal.md @@ -0,0 +1,21 @@ +# OpenGLCommandQueue::Signal + +```cpp +void Signal(RHIFence* fence, uint64_t value) +``` + +发送信号。 + +**参数:** +- `fence` - 围栏指针 +- `value` - 信号值 + +**示例:** + +```cpp +commandQueue->Signal(fence, 1); +``` + +## 相关文档 + +- [OpenGLCommandQueue](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/command-queue/wait-for-idle.md b/docs/api/rhi/opengl/command-queue/wait-for-idle.md new file mode 100644 index 0000000..7175e75 --- /dev/null +++ b/docs/api/rhi/opengl/command-queue/wait-for-idle.md @@ -0,0 +1,17 @@ +# OpenGLCommandQueue::WaitForIdle + +```cpp +void WaitForIdle() +``` + +等待命令队列空闲。 + +**示例:** + +```cpp +commandQueue->WaitForIdle(); +``` + +## 相关文档 + +- [OpenGLCommandQueue](command-queue.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/bind-framebuffer.md b/docs/api/rhi/opengl/depth-stencil-view/bind-framebuffer.md new file mode 100644 index 0000000..a737aa4 --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/bind-framebuffer.md @@ -0,0 +1,20 @@ +# OpenGLDepthStencilView::BindFramebuffer + +```cpp +static void BindFramebuffer(unsigned int framebuffer) +``` + +静态方法,将指定帧缓冲区绑定为当前深度模板帧缓冲区。 + +**参数:** +- `framebuffer` - 帧缓冲区 ID(0 表示解除绑定) + +**示例:** + +```cpp +OpenGLDepthStencilView::BindFramebuffer(dsv.GetFramebuffer()); +``` + +## 相关文档 + +- [OpenGLDepthStencilView](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/bind.md b/docs/api/rhi/opengl/depth-stencil-view/bind.md new file mode 100644 index 0000000..b0ba153 --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/bind.md @@ -0,0 +1,11 @@ +# OpenGLDepthStencilView::Bind + +```cpp +void Bind() const; +``` + +绑定深度模板视图。 + +## 相关文档 + +- [OpenGLDepthStencilView 总览](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/clear-depth-stencil.md b/docs/api/rhi/opengl/depth-stencil-view/clear-depth-stencil.md new file mode 100644 index 0000000..5f3f191 --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/clear-depth-stencil.md @@ -0,0 +1,21 @@ +# OpenGLDepthStencilView::ClearDepthStencil + +```cpp +void ClearDepthStencil(float depth, uint8_t stencil) +``` + +同时清除深度和模板缓冲区。 + +**参数:** +- `depth` - 深度值(通常为 0.0 到 1.0) +- `stencil` - 模板值(0-255) + +**示例:** + +```cpp +dsv.ClearDepthStencil(1.0f, 0); +``` + +## 相关文档 + +- [OpenGLDepthStencilView](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/clear-depth.md b/docs/api/rhi/opengl/depth-stencil-view/clear-depth.md new file mode 100644 index 0000000..8292a28 --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/clear-depth.md @@ -0,0 +1,20 @@ +# OpenGLDepthStencilView::ClearDepth + +```cpp +void ClearDepth(float depth) +``` + +清除深度缓冲区的深度值。 + +**参数:** +- `depth` - 深度值(通常为 0.0 到 1.0) + +**示例:** + +```cpp +dsv.ClearDepth(1.0f); +``` + +## 相关文档 + +- [OpenGLDepthStencilView](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/clear-stencil.md b/docs/api/rhi/opengl/depth-stencil-view/clear-stencil.md new file mode 100644 index 0000000..bca7b5d --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/clear-stencil.md @@ -0,0 +1,20 @@ +# OpenGLDepthStencilView::ClearStencil + +```cpp +void ClearStencil(uint8_t stencil) +``` + +清除模板缓冲区的模板值。 + +**参数:** +- `stencil` - 模板值(0-255) + +**示例:** + +```cpp +dsv.ClearStencil(0); +``` + +## 相关文档 + +- [OpenGLDepthStencilView](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/depth-stencil-view.md b/docs/api/rhi/opengl/depth-stencil-view/depth-stencil-view.md new file mode 100644 index 0000000..7f5c5e7 --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/depth-stencil-view.md @@ -0,0 +1,29 @@ +# OpenGLDepthStencilView + +**命名空间**: `XCEngine::RHI` + +**描述**: OpenGL 深度模板视图实现。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](initialize.md) | 初始化深度模板视图 | +| [`InitializeCubemap`](initialize-cubemap.md) | 初始化立方体贴图深度模板视图 | +| [`Shutdown`](shutdown.md) | 关闭深度模板视图 | +| [`Bind`](bind.md) | 绑定深度模板视图 | +| [`Unbind`](unbind.md) | 解绑深度模板视图 | +| [`ClearDepth`](clear-depth.md) | 清除深度 | +| [`ClearStencil`](clear-stencil.md) | 清除模板 | +| [`ClearDepthStencil`](clear-depth-stencil.md) | 清除深度和模板 | +| [`GetFramebuffer`](get-framebuffer.md) | 获取帧缓冲 | +| [`GetTexture`](get-texture.md) | 获取纹理 | +| [`GetMipLevel`](get-mip-level.md) | 获取 Mip 级别 | +| [`GetWidth`](get-size.md) | 获取宽度 | +| [`GetHeight`](get-size.md) | 获取高度 | +| [`BindFramebuffer`](bind-framebuffer.md) | 绑定帧缓冲 | +| [`UnbindFramebuffer`](unbind-framebuffer.md) | 解绑帧缓冲 | + +## 相关文档 + +- [OpenGL 后端总览](../overview.md) diff --git a/docs/api/rhi/opengl/depth-stencil-view/get-framebuffer.md b/docs/api/rhi/opengl/depth-stencil-view/get-framebuffer.md new file mode 100644 index 0000000..940b5a1 --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/get-framebuffer.md @@ -0,0 +1,19 @@ +# OpenGLDepthStencilView::GetFramebuffer + +```cpp +unsigned int GetFramebuffer() const +``` + +获取帧缓冲区对象 ID。 + +**返回:** `unsigned int` - 帧缓冲区 ID + +**示例:** + +```cpp +unsigned int fbo = dsv.GetFramebuffer(); +``` + +## 相关文档 + +- [OpenGLDepthStencilView](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/get-mip-level.md b/docs/api/rhi/opengl/depth-stencil-view/get-mip-level.md new file mode 100644 index 0000000..bc7cfce --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/get-mip-level.md @@ -0,0 +1,19 @@ +# OpenGLDepthStencilView::GetMipLevel + +```cpp +int GetMipLevel() const +``` + +获取 mipmap 级别。 + +**返回:** `int` - mip 级别 + +**示例:** + +```cpp +int mipLevel = dsv.GetMipLevel(); +``` + +## 相关文档 + +- [OpenGLDepthStencilView](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/get-size.md b/docs/api/rhi/opengl/depth-stencil-view/get-size.md new file mode 100644 index 0000000..58de988 --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/get-size.md @@ -0,0 +1,14 @@ +# OpenGLDepthStencilView::GetWidth / GetHeight + +```cpp +int GetWidth() const; +int GetHeight() const; +``` + +获取深度模板视图的宽度和高度。 + +**返回:** 宽度/高度 + +## 相关文档 + +- [OpenGLDepthStencilView 总览](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/get-texture.md b/docs/api/rhi/opengl/depth-stencil-view/get-texture.md new file mode 100644 index 0000000..7958415 --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/get-texture.md @@ -0,0 +1,19 @@ +# OpenGLDepthStencilView::GetTexture + +```cpp +unsigned int GetTexture() const +``` + +获取关联的纹理对象 ID。 + +**返回:** `unsigned int` - 纹理 ID + +**示例:** + +```cpp +unsigned int tex = dsv.GetTexture(); +``` + +## 相关文档 + +- [OpenGLDepthStencilView](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/initialize-cubemap.md b/docs/api/rhi/opengl/depth-stencil-view/initialize-cubemap.md new file mode 100644 index 0000000..40a5d86 --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/initialize-cubemap.md @@ -0,0 +1,25 @@ +# OpenGLDepthStencilView::InitializeCubemap + +```cpp +bool InitializeCubemap(unsigned int cubemap, int face, int mipLevel = 0) +``` + +初始化立方体贴图的深度模板视图。 + +**参数:** +- `cubemap` - 立方体贴图对象 ID +- `face` - 立方体贴面索引(0-5) +- `mipLevel` - mipmap 级别(默认为 0) + +**返回:** `bool` - 成功返回 true,失败返回 false + +**示例:** + +```cpp +OpenGLDepthStencilView dsv; +dsv.InitializeCubemap(cubemapTexture, 0, 0); +``` + +## 相关文档 + +- [OpenGLDepthStencilView](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/initialize.md b/docs/api/rhi/opengl/depth-stencil-view/initialize.md new file mode 100644 index 0000000..6e9b4ac --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/initialize.md @@ -0,0 +1,18 @@ +# OpenGLDepthStencilView::Initialize + +```cpp +bool Initialize(unsigned int texture, int width, int height); +``` + +初始化深度模板视图。 + +**参数:** +- `texture` - OpenGL 纹理 ID +- `width` - 宽度 +- `height` - 高度 + +**返回:** 成功返回 true + +## 相关文档 + +- [OpenGLDepthStencilView 总览](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/shutdown.md b/docs/api/rhi/opengl/depth-stencil-view/shutdown.md new file mode 100644 index 0000000..51497b7 --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/shutdown.md @@ -0,0 +1,11 @@ +# OpenGLDepthStencilView::Shutdown + +```cpp +void Shutdown(); +``` + +关闭深度模板视图。 + +## 相关文档 + +- [OpenGLDepthStencilView 总览](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/unbind-framebuffer.md b/docs/api/rhi/opengl/depth-stencil-view/unbind-framebuffer.md new file mode 100644 index 0000000..a686aa0 --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/unbind-framebuffer.md @@ -0,0 +1,17 @@ +# OpenGLDepthStencilView::UnbindFramebuffer + +```cpp +static void UnbindFramebuffer() +``` + +静态方法,解除当前深度模板帧缓冲区的绑定。 + +**示例:** + +```cpp +OpenGLDepthStencilView::UnbindFramebuffer(); +``` + +## 相关文档 + +- [OpenGLDepthStencilView](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/depth-stencil-view/unbind.md b/docs/api/rhi/opengl/depth-stencil-view/unbind.md new file mode 100644 index 0000000..1a010d3 --- /dev/null +++ b/docs/api/rhi/opengl/depth-stencil-view/unbind.md @@ -0,0 +1,11 @@ +# OpenGLDepthStencilView::Unbind + +```cpp +void Unbind() const; +``` + +解除绑定深度模板视图。 + +## 相关文档 + +- [OpenGLDepthStencilView 总览](depth-stencil-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/device/create-render-window.md b/docs/api/rhi/opengl/device/create-render-window.md new file mode 100644 index 0000000..24a800b --- /dev/null +++ b/docs/api/rhi/opengl/device/create-render-window.md @@ -0,0 +1,28 @@ +# OpenGLDevice::CreateRenderWindow + +```cpp +bool CreateRenderWindow(int width, int height, const char* title, bool enableDebug = false) +``` + +创建并初始化一个新的 GLFW 窗口,同时初始化 OpenGL 上下文。 + +**参数:** +- `width` - 窗口宽度(像素) +- `height` - 窗口高度(像素) +- `title` - 窗口标题 +- `enableDebug` - 是否启用 OpenGL 调试上下文(可选,默认为 false) + +**返回:** `bool` - 成功返回 true,失败返回 false + +**示例:** + +```cpp +OpenGLDevice device; +if (device.CreateRenderWindow(1280, 720, "XCEngine", false)) { + // 窗口创建成功,可以开始渲染循环 +} +``` + +## 相关文档 + +- [OpenGLDevice](device.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/device/device.md b/docs/api/rhi/opengl/device/device.md new file mode 100644 index 0000000..c63ade7 --- /dev/null +++ b/docs/api/rhi/opengl/device/device.md @@ -0,0 +1,37 @@ +# OpenGLDevice + +**命名空间**: `XCEngine::RHI` + +**描述**: OpenGL 设备的实现,继承自 `RHIDevice`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化设备 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭设备 | +| [`CreateRenderWindow`](create-render-window.md) | 创建渲染窗口 | +| [`InitializeWithExistingWindow`](initialize-with-existing-window.md) | 使用现有窗口初始化 | +| [`GetWindow`](get-window.md) | 获取窗口 | +| [`SwapBuffers`](swap-buffers.md) | 交换缓冲 | +| [`PollEvents`](poll-events.md) | 处理窗口事件 | +| [`SetShouldClose`](set-should-close.md) | 设置关闭标志 | +| [`ShouldClose`](should-close.md) | 检查是否应关闭 | +| [`CreateBuffer`](../../device/create-buffer.md) | 创建缓冲区 | +| [`CreateTexture`](../../device/create-texture.md) | 创建纹理 | +| [`CreateSwapChain`](../../device/create-swap-chain.md) | 创建交换链 | +| [`CreateCommandList`](../../device/create-command-list.md) | 创建命令列表 | +| [`CreateCommandQueue`](../../device/create-command-queue.md) | 创建命令队列 | +| [`CompileShader`](../../device/compile-shader.md) | 编译着色器 | +| [`CreatePipelineState`](../../device/create-pipeline-state.md) | 创建管线状态 | +| [`CreateFence`](../../device/create-fence.md) | 创建栅栏 | +| [`CreateSampler`](../../device/create-sampler.md) | 创建采样器 | +| [`GetCapabilities`](../../device/get-capabilities.md) | 获取设备能力 | +| [`GetDeviceInfo`](../../device/get-device-info.md) | 获取设备信息 | +| [`GetNativeDevice`](../../device/get-native-device.md) | 获取原生设备 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | + +## 相关文档 + +- [OpenGL 后端总览](../overview.md) +- [RHIDevice](../../device/device.md) - 抽象设备接口 diff --git a/docs/api/rhi/opengl/device/get-window.md b/docs/api/rhi/opengl/device/get-window.md new file mode 100644 index 0000000..288b5da --- /dev/null +++ b/docs/api/rhi/opengl/device/get-window.md @@ -0,0 +1,22 @@ +# OpenGLDevice::GetWindow + +```cpp +GLFWwindow* GetWindow() const +``` + +获取关联的 GLFW 窗口指针。 + +**返回:** `GLFWwindow*` - GLFW 窗口指针 + +**示例:** + +```cpp +GLFWwindow* window = device.GetWindow(); +if (window) { + glfwSetWindowTitle(window, "New Title"); +} +``` + +## 相关文档 + +- [OpenGLDevice](device.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/device/initialize-with-existing-window.md b/docs/api/rhi/opengl/device/initialize-with-existing-window.md new file mode 100644 index 0000000..939fd69 --- /dev/null +++ b/docs/api/rhi/opengl/device/initialize-with-existing-window.md @@ -0,0 +1,26 @@ +# OpenGLDevice::InitializeWithExistingWindow + +```cpp +bool InitializeWithExistingWindow(GLFWwindow* window) +``` + +使用已有的 GLFW 窗口初始化 OpenGL 设备,不会创建新窗口或管理窗口生命周期。 + +**参数:** +- `window` - 已存在的 GLFWwindow 指针 + +**返回:** `bool` - 成功返回 true,失败返回 false + +**示例:** + +```cpp +GLFWwindow* existingWindow = glfwCreateWindow(1280, 720, "Existing", nullptr, nullptr); +OpenGLDevice device; +if (device.InitializeWithExistingWindow(existingWindow)) { + // 使用已有窗口初始化设备 +} +``` + +## 相关文档 + +- [OpenGLDevice](device.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/device/poll-events.md b/docs/api/rhi/opengl/device/poll-events.md new file mode 100644 index 0000000..4d26430 --- /dev/null +++ b/docs/api/rhi/opengl/device/poll-events.md @@ -0,0 +1,23 @@ +# OpenGLDevice::PollEvents + +```cpp +bool PollEvents() +``` + +处理所有挂起的 GLFW 事件(窗口事件、输入事件等)。 + +**返回:** `bool` - 如果窗口应保持打开返回 true,如果窗口应关闭返回 false + +**示例:** + +```cpp +while (device.PollEvents()) { + // 渲染和交换缓冲区 + renderScene(); + device.SwapBuffers(); +} +``` + +## 相关文档 + +- [OpenGLDevice](device.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/device/set-should-close.md b/docs/api/rhi/opengl/device/set-should-close.md new file mode 100644 index 0000000..3cc2212 --- /dev/null +++ b/docs/api/rhi/opengl/device/set-should-close.md @@ -0,0 +1,20 @@ +# OpenGLDevice::SetShouldClose + +```cpp +void SetShouldClose(bool shouldClose) +``` + +设置窗口是否应该关闭的标志。 + +**参数:** +- `shouldClose` - true 表示窗口应该关闭,false 表示保持打开 + +**示例:** + +```cpp +device.SetShouldClose(true); // 请求关闭窗口 +``` + +## 相关文档 + +- [OpenGLDevice](device.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/device/should-close.md b/docs/api/rhi/opengl/device/should-close.md new file mode 100644 index 0000000..c75d4f5 --- /dev/null +++ b/docs/api/rhi/opengl/device/should-close.md @@ -0,0 +1,23 @@ +# OpenGLDevice::ShouldClose + +```cpp +bool ShouldClose() const +``` + +检查窗口是否应该关闭。 + +**返回:** `bool` - 如果窗口应该关闭返回 true,否则返回 false + +**示例:** + +```cpp +while (!device.ShouldClose()) { + device.PollEvents(); + renderScene(); + device.SwapBuffers(); +} +``` + +## 相关文档 + +- [OpenGLDevice](device.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/device/swap-buffers.md b/docs/api/rhi/opengl/device/swap-buffers.md new file mode 100644 index 0000000..444d30d --- /dev/null +++ b/docs/api/rhi/opengl/device/swap-buffers.md @@ -0,0 +1,19 @@ +# OpenGLDevice::SwapBuffers + +```cpp +void SwapBuffers() +``` + +交换前后缓冲区,将渲染内容显示到屏幕上。 + +**示例:** + +```cpp +// 渲染完成后交换缓冲区 +renderScene(); +device.SwapBuffers(); +``` + +## 相关文档 + +- [OpenGLDevice](device.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/fence/fence.md b/docs/api/rhi/opengl/fence/fence.md new file mode 100644 index 0000000..4a50e3d --- /dev/null +++ b/docs/api/rhi/opengl/fence/fence.md @@ -0,0 +1,25 @@ +# OpenGLFence + +**命名空间**: `XCEngine::RHI` + +**描述**: OpenGL 栅栏同步实现,继承自 `RHIFence`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](initialize.md) | 初始化栅栏 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭栅栏 | +| [`Signal`](signal.md) | 信号栅栏 | +| [`Wait`](../../../threading/task-group/wait.md) | 等待栅栏 | +| [`Reset`](reset.md) | 重置栅栏 | +| [`IsSignaled`](is-signaled.md) | 检查是否已信号 | +| [`GetStatus`](get-status.md) | 获取状态 | +| [`GetCompletedValue`](get-completed-value.md) | 获取完成值 | +| [`GetCurrentValue`](get-current-value.md) | 获取当前值 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | + +## 相关文档 + +- [OpenGL 后端总览](../overview.md) +- [RHIFence](../../fence/fence.md) - 抽象栅栏接口 diff --git a/docs/api/rhi/opengl/fence/get-completed-value.md b/docs/api/rhi/opengl/fence/get-completed-value.md new file mode 100644 index 0000000..0d03ce1 --- /dev/null +++ b/docs/api/rhi/opengl/fence/get-completed-value.md @@ -0,0 +1,19 @@ +# OpenGLFence::GetCompletedValue + +```cpp +uint64_t GetCompletedValue() const override +``` + +获取已完成的最大栅栏值。 + +**返回:** `uint64_t` - 已完成的栅栏值 + +**示例:** + +```cpp +uint64_t completed = fence.GetCompletedValue(); +``` + +## 相关文档 + +- [OpenGLFence](fence.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/fence/get-current-value.md b/docs/api/rhi/opengl/fence/get-current-value.md new file mode 100644 index 0000000..22433f9 --- /dev/null +++ b/docs/api/rhi/opengl/fence/get-current-value.md @@ -0,0 +1,19 @@ +# OpenGLFence::GetCurrentValue + +```cpp +uint64_t GetCurrentValue() const +``` + +获取栅栏的当前值。 + +**返回:** `uint64_t` - 当前栅栏值 + +**示例:** + +```cpp +uint64_t current = fence.GetCurrentValue(); +``` + +## 相关文档 + +- [OpenGLFence](fence.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/fence/get-status.md b/docs/api/rhi/opengl/fence/get-status.md new file mode 100644 index 0000000..e941216 --- /dev/null +++ b/docs/api/rhi/opengl/fence/get-status.md @@ -0,0 +1,25 @@ +# OpenGLFence::GetStatus + +```cpp +FenceStatus GetStatus() const +``` + +获取栅栏的当前状态。 + +**返回:** `FenceStatus` - 栅栏状态,可能的值: +- `FenceStatus::Signaled` - 栅栏已signaled +- `FenceStatus::Unsignaled` - 栅栏未signaled +- `FenceStatus::Error` - 发生错误 + +**示例:** + +```cpp +FenceStatus status = fence.GetStatus(); +if (status == FenceStatus::Signaled) { + // 操作已完成 +} +``` + +## 相关文档 + +- [OpenGLFence](fence.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/fence/initialize.md b/docs/api/rhi/opengl/fence/initialize.md new file mode 100644 index 0000000..ca64bb0 --- /dev/null +++ b/docs/api/rhi/opengl/fence/initialize.md @@ -0,0 +1,23 @@ +# OpenGLFence::Initialize + +```cpp +bool Initialize(bool signaled = false); +``` + +初始化 OpenGL 栅栏。 + +**参数:** +- `signaled` - 初始是否为 signaled 状态 + +**返回:** 成功返回 true + +**示例:** + +```cpp +OpenGLFence fence; +fence.Initialize(true); +``` + +## 相关文档 + +- [OpenGLFence 总览](fence.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/fence/is-signaled.md b/docs/api/rhi/opengl/fence/is-signaled.md new file mode 100644 index 0000000..8ec86c8 --- /dev/null +++ b/docs/api/rhi/opengl/fence/is-signaled.md @@ -0,0 +1,21 @@ +# OpenGLFence::IsSignaled + +```cpp +bool IsSignaled() const override +``` + +检查栅栏是否处于 signaled 状态。 + +**返回:** `bool` - 如果栅栏已signaled返回 true,否则返回 false + +**示例:** + +```cpp +if (fence.IsSignaled()) { + // 可以安全地继续执行 +} +``` + +## 相关文档 + +- [OpenGLFence](fence.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/fence/reset.md b/docs/api/rhi/opengl/fence/reset.md new file mode 100644 index 0000000..a395126 --- /dev/null +++ b/docs/api/rhi/opengl/fence/reset.md @@ -0,0 +1,17 @@ +# OpenGLFence::Reset + +```cpp +void Reset(); +``` + +重置栅栏。 + +**示例:** + +```cpp +fence->Reset(); +``` + +## 相关文档 + +- [OpenGLFence 总览](fence.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/fence/signal.md b/docs/api/rhi/opengl/fence/signal.md new file mode 100644 index 0000000..52eb47a --- /dev/null +++ b/docs/api/rhi/opengl/fence/signal.md @@ -0,0 +1,20 @@ +# OpenGLFence::Signal + +```cpp +void Signal() override +void Signal(uint64_t value) override +``` + +将栅栏设置为 signaled 状态,通知等待的线程操作完成。 + +**示例:** + +```cpp +OpenGLFence fence; +fence.Initialize(false); +fence.Signal(); +``` + +## 相关文档 + +- [OpenGLFence](fence.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/overview.md b/docs/api/rhi/opengl/overview.md new file mode 100644 index 0000000..777487f --- /dev/null +++ b/docs/api/rhi/opengl/overview.md @@ -0,0 +1,41 @@ +# OpenGL 后端概览 + +**命名空间**: `XCEngine::RHI` + +**类型**: `module` + +**描述**: OpenGL 后端实现模块,基于 GLFW 和现代 OpenGL (Core Profile)。 + +## 组件列表 + +| 组件 | 文档 | +|------|------| +| [OpenGLDevice](device/device.md) | OpenGL 设备实现 | +| [OpenGLBuffer](buffer/buffer.md) | OpenGL 缓冲区实现 | +| [OpenGLTexture](texture/texture.md) | OpenGL 纹理实现 | +| [OpenGLCommandList](command-list/command-list.md) | OpenGL 命令列表实现 | +| [OpenGLCommandQueue](command-queue/command-queue.md) | OpenGL 命令队列实现 | +| [OpenGLSwapChain](swap-chain/swap-chain.md) | OpenGL 交换链实现 | +| [OpenGLFence](fence/fence.md) | OpenGL 同步栅栏实现 | +| [OpenGLShader](shader/shader.md) | OpenGL 着色器实现 | +| [OpenGLPipelineState](pipeline-state/pipeline-state.md) | OpenGL 管线状态实现 | +| [OpenGLSampler](sampler/sampler.md) | OpenGL 采样器实现 | +| [OpenGLVertexArray](vertex-array/vertex-array.md) | OpenGL 顶点数组实现 | +| [OpenGLRenderTargetView](render-target-view/render-target-view.md) | OpenGL 渲染目标实现 | +| [OpenGLDepthStencilView](depth-stencil-view/depth-stencil-view.md) | OpenGL 深度模板实现 | + +## 与 D3D12 的差异 + +| 方面 | D3D12 | OpenGL | +|------|-------|--------| +| 模式 | 命令列表录制 | 立即模式 | +| 状态管理 | 显式资源状态 | OpenGL 状态机 | +| 描述符 | 描述符堆 + 句柄 | 绑定点 | +| 管线状态 | PSO(不可变) | 可变状态 | +| 内存管理 | 显式显存管理 | 驱动自动管理 | +| 多线程 | 需要 Bundle | 上下文共享 | + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [D3D12 后端](overview.md) diff --git a/docs/api/rhi/opengl/pipeline-state/apply-blend.md b/docs/api/rhi/opengl/pipeline-state/apply-blend.md new file mode 100644 index 0000000..c4fcc3b --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/apply-blend.md @@ -0,0 +1,21 @@ +# OpenGLPipelineState::ApplyBlend + +```cpp +void ApplyBlend(); +``` + +应用混合状态到 OpenGL。 + +**线程安全:** ❌ + +**示例:** + +```cpp +pipelineState->SetBlendState(blendState); +pipelineState->ApplyBlend(); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [Apply](apply.md) - 应用所有状态 diff --git a/docs/api/rhi/opengl/pipeline-state/apply-depth-stencil.md b/docs/api/rhi/opengl/pipeline-state/apply-depth-stencil.md new file mode 100644 index 0000000..2470242 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/apply-depth-stencil.md @@ -0,0 +1,21 @@ +# OpenGLPipelineState::ApplyDepthStencil + +```cpp +void ApplyDepthStencil(); +``` + +应用深度模板状态到 OpenGL。 + +**线程安全:** ❌ + +**示例:** + +```cpp +pipelineState->SetDepthStencilState(dsState); +pipelineState->ApplyDepthStencil(); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [Apply](apply.md) - 应用所有状态 diff --git a/docs/api/rhi/opengl/pipeline-state/apply-rasterizer.md b/docs/api/rhi/opengl/pipeline-state/apply-rasterizer.md new file mode 100644 index 0000000..45fd9c9 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/apply-rasterizer.md @@ -0,0 +1,21 @@ +# OpenGLPipelineState::ApplyRasterizer + +```cpp +void ApplyRasterizer(); +``` + +应用光栅化状态到 OpenGL。 + +**线程安全:** ❌ + +**示例:** + +```cpp +pipelineState->SetRasterizerState(rsState); +pipelineState->ApplyRasterizer(); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [Apply](apply.md) - 应用所有状态 diff --git a/docs/api/rhi/opengl/pipeline-state/apply-scissor.md b/docs/api/rhi/opengl/pipeline-state/apply-scissor.md new file mode 100644 index 0000000..8716bf2 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/apply-scissor.md @@ -0,0 +1,21 @@ +# OpenGLPipelineState::ApplyScissor + +```cpp +void ApplyScissor(); +``` + +应用裁剪状态到 OpenGL。 + +**线程安全:** ❌ + +**示例:** + +```cpp +pipelineState->SetScissor(scissor); +pipelineState->ApplyScissor(); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [Apply](apply.md) - 应用所有状态 diff --git a/docs/api/rhi/opengl/pipeline-state/apply-viewport.md b/docs/api/rhi/opengl/pipeline-state/apply-viewport.md new file mode 100644 index 0000000..2bcbe67 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/apply-viewport.md @@ -0,0 +1,21 @@ +# OpenGLPipelineState::ApplyViewport + +```cpp +void ApplyViewport(); +``` + +应用视口状态到 OpenGL。 + +**线程安全:** ❌ + +**示例:** + +```cpp +pipelineState->SetViewport(viewport); +pipelineState->ApplyViewport(); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [Apply](apply.md) - 应用所有状态 diff --git a/docs/api/rhi/opengl/pipeline-state/apply.md b/docs/api/rhi/opengl/pipeline-state/apply.md new file mode 100644 index 0000000..1878101 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/apply.md @@ -0,0 +1,27 @@ +# OpenGLPipelineState::Apply + +```cpp +void Apply(); +``` + +应用所有管线状态(深度模板、混合、光栅化、视口、裁剪)。 + +**线程安全:** ❌ + +**示例:** + +```cpp +pipelineState->SetDepthStencilState(dsState); +pipelineState->SetBlendState(blendState); +pipelineState->SetRasterizerState(rsState); +pipelineState->SetViewport(viewport); +pipelineState->SetScissor(scissor); +pipelineState->Apply(); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [ApplyDepthStencil](apply-depth-stencil.md) - 仅应用深度模板 +- [ApplyBlend](apply-blend.md) - 仅应用混合 +- [ApplyRasterizer](apply-rasterizer.md) - 仅应用光栅化 diff --git a/docs/api/rhi/opengl/pipeline-state/attach-shader.md b/docs/api/rhi/opengl/pipeline-state/attach-shader.md new file mode 100644 index 0000000..db34811 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/attach-shader.md @@ -0,0 +1,23 @@ +# OpenGLPipelineState::AttachShader + +```cpp +void AttachShader(unsigned int program); +``` + +附加 OpenGL 着色器程序到管线状态。 + +**参数:** +- `program` - OpenGL 着色器程序 ID + +**线程安全:** ❌ + +**示例:** + +```cpp +pipelineState->AttachShader(shaderProgram); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [DetachShader](detach-shader.md) - 分离着色器程序 diff --git a/docs/api/rhi/opengl/pipeline-state/detach-shader.md b/docs/api/rhi/opengl/pipeline-state/detach-shader.md new file mode 100644 index 0000000..3b98083 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/detach-shader.md @@ -0,0 +1,20 @@ +# OpenGLPipelineState::DetachShader + +```cpp +void DetachShader(); +``` + +从管线状态分离着色器程序。 + +**线程安全:** ❌ + +**示例:** + +```cpp +pipelineState->DetachShader(); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [AttachShader](attach-shader.md) - 附加着色器程序 diff --git a/docs/api/rhi/opengl/pipeline-state/get-blend-state.md b/docs/api/rhi/opengl/pipeline-state/get-blend-state.md new file mode 100644 index 0000000..9f3a318 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/get-blend-state.md @@ -0,0 +1,25 @@ +# OpenGLPipelineState::GetBlendState + +```cpp +const OpenGLBlendState& GetBlendState() const; +``` + +获取当前混合状态。 + +**返回:** 混合状态结构体引用 + +**线程安全:** ❌ + +**示例:** + +```cpp +const auto& blendState = pipelineState->GetBlendState(); +if (blendState.blendEnable) { + // blend is enabled +} +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [SetBlendState](set-blend-state.md) - 设置混合状态 diff --git a/docs/api/rhi/opengl/pipeline-state/get-depth-stencil-state.md b/docs/api/rhi/opengl/pipeline-state/get-depth-stencil-state.md new file mode 100644 index 0000000..6f98d6f --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/get-depth-stencil-state.md @@ -0,0 +1,25 @@ +# OpenGLPipelineState::GetDepthStencilState + +```cpp +const OpenGLDepthStencilState& GetDepthStencilState() const; +``` + +获取当前深度模板状态。 + +**返回:** 深度模板状态结构体引用 + +**线程安全:** ❌ + +**示例:** + +```cpp +const auto& dsState = pipelineState->GetDepthStencilState(); +if (dsState.depthTestEnable) { + // depth test is enabled +} +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [SetDepthStencilState](set-depth-stencil-state.md) - 设置深度模板状态 diff --git a/docs/api/rhi/opengl/pipeline-state/get-rasterizer-state.md b/docs/api/rhi/opengl/pipeline-state/get-rasterizer-state.md new file mode 100644 index 0000000..333563d --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/get-rasterizer-state.md @@ -0,0 +1,25 @@ +# OpenGLPipelineState::GetRasterizerState + +```cpp +const OpenGLRasterizerState& GetRasterizerState() const; +``` + +获取当前光栅化状态。 + +**返回:** 光栅化状态结构体引用 + +**线程安全:** ❌ + +**示例:** + +```cpp +const auto& rsState = pipelineState->GetRasterizerState(); +if (rsState.cullFaceEnable) { + // culling is enabled +} +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [SetRasterizerState](set-rasterizer-state.md) - 设置光栅化状态 diff --git a/docs/api/rhi/opengl/pipeline-state/pipeline-state.md b/docs/api/rhi/opengl/pipeline-state/pipeline-state.md new file mode 100644 index 0000000..9b853bd --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/pipeline-state.md @@ -0,0 +1,39 @@ +# OpenGLPipelineState + +**命名空间**: `XCEngine::RHI` + +**描述**: OpenGL 管线状态对象实现,继承自 `RHIPipelineState`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭管线状态 | +| [`Bind`](../../shader/bind.md) | 绑定管线状态 | +| [`Unbind`](../../shader/unbind.md) | 解绑管线状态 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | +| [`GetType`](../../command-queue/get-type.md) | 获取管线类型 | +| [`SetDepthStencilState`](set-depth-stencil-state.md) | 设置深度模板状态 | +| [`SetBlendState`](set-blend-state.md) | 设置混合状态 | +| [`SetRasterizerState`](set-rasterizer-state.md) | 设置光栅化状态 | +| [`SetViewport`](set-viewport.md) | 设置视口 | +| [`SetScissor`](set-scissor.md) | 设置裁剪 | +| [`SetLogicalOperation`](set-logical-operation.md) | 设置逻辑操作 | +| [`Apply`](apply.md) | 应用管线状态 | +| [`ApplyDepthStencil`](apply-depth-stencil.md) | 应用深度模板状态 | +| [`ApplyBlend`](apply-blend.md) | 应用混合状态 | +| [`ApplyRasterizer`](apply-rasterizer.md) | 应用光栅化状态 | +| [`ApplyViewport`](apply-viewport.md) | 应用视口 | +| [`ApplyScissor`](apply-scissor.md) | 应用裁剪 | +| [`SetClearColor`](set-clear-color.md) | 设置清除颜色 | +| [`Clear`](../../command-list/clear.md) | 清除 | +| [`AttachShader`](attach-shader.md) | 附加着色器 | +| [`DetachShader`](detach-shader.md) | 分离着色器 | +| [`GetDepthStencilState`](get-depth-stencil-state.md) | 获取深度模板状态 | +| [`GetBlendState`](get-blend-state.md) | 获取混合状态 | +| [`GetRasterizerState`](get-rasterizer-state.md) | 获取光栅化状态 | + +## 相关文档 + +- [OpenGL 后端总览](../overview.md) +- [RHIPipelineState](../../pipeline-state/pipeline-state.md) - 抽象管线状态接口 diff --git a/docs/api/rhi/opengl/pipeline-state/set-blend-state.md b/docs/api/rhi/opengl/pipeline-state/set-blend-state.md new file mode 100644 index 0000000..5f121d5 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/set-blend-state.md @@ -0,0 +1,27 @@ +# OpenGLPipelineState::SetBlendState + +```cpp +void SetBlendState(const OpenGLBlendState& state); +``` + +设置混合状态。 + +**参数:** +- `state` - 混合状态结构体 + +**线程安全:** ❌ + +**示例:** + +```cpp +OpenGLBlendState blendState; +blendState.blendEnable = true; +blendState.srcBlend = BlendFactor::SrcAlpha; +blendState.dstBlend = BlendFactor::InvSrcAlpha; +pipelineState->SetBlendState(blendState); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [GetBlendState](get-blend-state.md) - 获取混合状态 diff --git a/docs/api/rhi/opengl/pipeline-state/set-clear-color.md b/docs/api/rhi/opengl/pipeline-state/set-clear-color.md new file mode 100644 index 0000000..eca1f25 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/set-clear-color.md @@ -0,0 +1,26 @@ +# OpenGLPipelineState::SetClearColor + +```cpp +void SetClearColor(float r, float g, float b, float a); +``` + +设置清除颜色值。 + +**参数:** +- `r` - 红色通道 (0.0 ~ 1.0) +- `g` - 绿色通道 (0.0 ~ 1.0) +- `b` - 蓝色通道 (0.0 ~ 1.0) +- `a` - Alpha 通道 (0.0 ~ 1.0) + +**线程安全:** ❌ + +**示例:** + +```cpp +pipelineState->SetClearColor(0.1f, 0.1f, 0.1f, 1.0f); +pipelineState->Clear(GL_COLOR_BUFFER_BIT); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/pipeline-state/set-depth-stencil-state.md b/docs/api/rhi/opengl/pipeline-state/set-depth-stencil-state.md new file mode 100644 index 0000000..e634653 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/set-depth-stencil-state.md @@ -0,0 +1,27 @@ +# OpenGLPipelineState::SetDepthStencilState + +```cpp +void SetDepthStencilState(const OpenGLDepthStencilState& state); +``` + +设置深度模板状态。 + +**参数:** +- `state` - 深度模板状态结构体 + +**线程安全:** ❌ + +**示例:** + +```cpp +OpenGLDepthStencilState dsState; +dsState.depthTestEnable = true; +dsState.depthWriteEnable = true; +dsState.depthFunc = ComparisonFunc::Less; +pipelineState->SetDepthStencilState(dsState); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [GetDepthStencilState](get-depth-stencil-state.md) - 获取深度模板状态 diff --git a/docs/api/rhi/opengl/pipeline-state/set-logical-operation.md b/docs/api/rhi/opengl/pipeline-state/set-logical-operation.md new file mode 100644 index 0000000..531f544 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/set-logical-operation.md @@ -0,0 +1,25 @@ +# OpenGLPipelineState::SetLogicalOperation + +```cpp +void SetLogicalOperation(const LogicalOperation& state); +``` + +设置逻辑操作状态。 + +**参数:** +- `state` - 逻辑操作状态结构体 + +**线程安全:** ❌ + +**示例:** + +```cpp +LogicalOperation op; +op.enable = false; +op.operation = 0; +pipelineState->SetLogicalOperation(op); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/pipeline-state/set-rasterizer-state.md b/docs/api/rhi/opengl/pipeline-state/set-rasterizer-state.md new file mode 100644 index 0000000..c46b991 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/set-rasterizer-state.md @@ -0,0 +1,27 @@ +# OpenGLPipelineState::SetRasterizerState + +```cpp +void SetRasterizerState(const OpenGLRasterizerState& state); +``` + +设置光栅化状态。 + +**参数:** +- `state` - 光栅化状态结构体 + +**线程安全:** ❌ + +**示例:** + +```cpp +OpenGLRasterizerState rsState; +rsState.cullFaceEnable = true; +rsState.cullFace = CullFace::Back; +rsState.frontFace = FrontFace::CounterClockwise; +pipelineState->SetRasterizerState(rsState); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [GetRasterizerState](get-rasterizer-state.md) - 获取光栅化状态 diff --git a/docs/api/rhi/opengl/pipeline-state/set-scissor.md b/docs/api/rhi/opengl/pipeline-state/set-scissor.md new file mode 100644 index 0000000..d930188 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/set-scissor.md @@ -0,0 +1,29 @@ +# OpenGLPipelineState::SetScissor + +```cpp +void SetScissor(const ScissorState& state); +``` + +设置裁剪状态。 + +**参数:** +- `state` - 裁剪状态结构体 + +**线程安全:** ❌ + +**示例:** + +```cpp +ScissorState scissor; +scissor.enable = true; +scissor.x = 0; +scissor.y = 0; +scissor.width = 1920; +scissor.height = 1080; +pipelineState->SetScissor(scissor); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [ApplyScissor](apply-scissor.md) - 应用裁剪状态 diff --git a/docs/api/rhi/opengl/pipeline-state/set-viewport.md b/docs/api/rhi/opengl/pipeline-state/set-viewport.md new file mode 100644 index 0000000..1e5e5f1 --- /dev/null +++ b/docs/api/rhi/opengl/pipeline-state/set-viewport.md @@ -0,0 +1,30 @@ +# OpenGLPipelineState::SetViewport + +```cpp +void SetViewport(const ViewportState& state); +``` + +设置视口状态。 + +**参数:** +- `state` - 视口状态结构体 + +**线程安全:** ❌ + +**示例:** + +```cpp +ViewportState viewport; +viewport.x = 0; +viewport.y = 0; +viewport.width = 1920; +viewport.height = 1080; +viewport.minDepth = 0.0f; +viewport.maxDepth = 1.0f; +pipelineState->SetViewport(viewport); +``` + +## 相关文档 + +- [OpenGLPipelineState 总览](pipeline-state.md) - 返回类总览 +- [ApplyViewport](apply-viewport.md) - 应用视口状态 diff --git a/docs/api/rhi/opengl/render-target-view/bind-framebuffer.md b/docs/api/rhi/opengl/render-target-view/bind-framebuffer.md new file mode 100644 index 0000000..969ff3f --- /dev/null +++ b/docs/api/rhi/opengl/render-target-view/bind-framebuffer.md @@ -0,0 +1,20 @@ +# OpenGLRenderTargetView::BindFramebuffer + +```cpp +static void BindFramebuffer(unsigned int framebuffer) +``` + +静态方法,将指定帧缓冲区绑定为当前渲染目标。 + +**参数:** +- `framebuffer` - 帧缓冲区 ID(0 表示解除绑定) + +**示例:** + +```cpp +OpenGLRenderTargetView::BindFramebuffer(rtv.GetFramebuffer()); +``` + +## 相关文档 + +- [OpenGLRenderTargetView](render-target-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/render-target-view/bind.md b/docs/api/rhi/opengl/render-target-view/bind.md new file mode 100644 index 0000000..4a621cf --- /dev/null +++ b/docs/api/rhi/opengl/render-target-view/bind.md @@ -0,0 +1,11 @@ +# OpenGLRenderTargetView::Bind + +```cpp +void Bind() const; +``` + +绑定渲染目标视图。 + +## 相关文档 + +- [OpenGLRenderTargetView 总览](render-target-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/render-target-view/clear.md b/docs/api/rhi/opengl/render-target-view/clear.md new file mode 100644 index 0000000..36c1541 --- /dev/null +++ b/docs/api/rhi/opengl/render-target-view/clear.md @@ -0,0 +1,17 @@ +# OpenGLRenderTargetView::Clear + +```cpp +void Clear(float r, float g, float b, float a); +``` + +清除渲染目标视图。 + +**参数:** +- `r` - 红色分量 +- `g` - 绿色分量 +- `b` - 蓝色分量 +- `a` - Alpha 分量 + +## 相关文档 + +- [OpenGLRenderTargetView 总览](render-target-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/render-target-view/get-framebuffer.md b/docs/api/rhi/opengl/render-target-view/get-framebuffer.md new file mode 100644 index 0000000..cb6d40f --- /dev/null +++ b/docs/api/rhi/opengl/render-target-view/get-framebuffer.md @@ -0,0 +1,19 @@ +# OpenGLRenderTargetView::GetFramebuffer + +```cpp +unsigned int GetFramebuffer() const +``` + +获取帧缓冲区对象 ID。 + +**返回:** `unsigned int` - 帧缓冲区 ID + +**示例:** + +```cpp +unsigned int fbo = rtv.GetFramebuffer(); +``` + +## 相关文档 + +- [OpenGLRenderTargetView](render-target-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/render-target-view/get-mip-level.md b/docs/api/rhi/opengl/render-target-view/get-mip-level.md new file mode 100644 index 0000000..a791bad --- /dev/null +++ b/docs/api/rhi/opengl/render-target-view/get-mip-level.md @@ -0,0 +1,19 @@ +# OpenGLRenderTargetView::GetMipLevel + +```cpp +int GetMipLevel() const +``` + +获取 mipmap 级别。 + +**返回:** `int` - mip 级别 + +**示例:** + +```cpp +int mipLevel = rtv.GetMipLevel(); +``` + +## 相关文档 + +- [OpenGLRenderTargetView](render-target-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/render-target-view/get-size.md b/docs/api/rhi/opengl/render-target-view/get-size.md new file mode 100644 index 0000000..eacc3d4 --- /dev/null +++ b/docs/api/rhi/opengl/render-target-view/get-size.md @@ -0,0 +1,14 @@ +# OpenGLRenderTargetView::GetWidth / GetHeight + +```cpp +int GetWidth() const; +int GetHeight() const; +``` + +获取渲染目标视图的宽度和高度。 + +**返回:** 宽度/高度 + +## 相关文档 + +- [OpenGLRenderTargetView 总览](render-target-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/render-target-view/get-texture.md b/docs/api/rhi/opengl/render-target-view/get-texture.md new file mode 100644 index 0000000..e3b9af5 --- /dev/null +++ b/docs/api/rhi/opengl/render-target-view/get-texture.md @@ -0,0 +1,19 @@ +# OpenGLRenderTargetView::GetTexture + +```cpp +unsigned int GetTexture() const +``` + +获取关联的纹理对象 ID。 + +**返回:** `unsigned int` - 纹理 ID + +**示例:** + +```cpp +unsigned int tex = rtv.GetTexture(); +``` + +## 相关文档 + +- [OpenGLRenderTargetView](render-target-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/render-target-view/initialize-cubemap.md b/docs/api/rhi/opengl/render-target-view/initialize-cubemap.md new file mode 100644 index 0000000..b960da5 --- /dev/null +++ b/docs/api/rhi/opengl/render-target-view/initialize-cubemap.md @@ -0,0 +1,25 @@ +# OpenGLRenderTargetView::InitializeCubemap + +```cpp +bool InitializeCubemap(unsigned int cubemap, int face, int mipLevel = 0) +``` + +初始化立方体贴图的渲染目标视图。 + +**参数:** +- `cubemap` - 立方体贴图对象 ID +- `face` - 立方体贴面索引(0-5) +- `mipLevel` - mipmap 级别(默认为 0) + +**返回:** `bool` - 成功返回 true,失败返回 false + +**示例:** + +```cpp +OpenGLRenderTargetView rtv; +rtv.InitializeCubemap(cubemapTexture, 0, 0); +``` + +## 相关文档 + +- [OpenGLRenderTargetView](render-target-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/render-target-view/initialize.md b/docs/api/rhi/opengl/render-target-view/initialize.md new file mode 100644 index 0000000..d3f48c6 --- /dev/null +++ b/docs/api/rhi/opengl/render-target-view/initialize.md @@ -0,0 +1,18 @@ +# OpenGLRenderTargetView::Initialize + +```cpp +bool Initialize(unsigned int texture, int width, int height); +``` + +初始化渲染目标视图。 + +**参数:** +- `texture` - OpenGL 纹理 ID +- `width` - 宽度 +- `height` - 高度 + +**返回:** 成功返回 true + +## 相关文档 + +- [OpenGLRenderTargetView 总览](render-target-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/render-target-view/render-target-view.md b/docs/api/rhi/opengl/render-target-view/render-target-view.md new file mode 100644 index 0000000..5d071bb --- /dev/null +++ b/docs/api/rhi/opengl/render-target-view/render-target-view.md @@ -0,0 +1,27 @@ +# OpenGLRenderTargetView + +**命名空间**: `XCEngine::RHI` + +**描述**: OpenGL 渲染目标视图实现。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](initialize.md) | 初始化渲染目标视图 | +| [`InitializeCubemap`](initialize-cubemap.md) | 初始化立方体贴图渲染目标视图 | +| [`Shutdown`](shutdown.md) | 关闭渲染目标视图 | +| [`Bind`](bind.md) | 绑定渲染目标视图 | +| [`Unbind`](unbind.md) | 解绑渲染目标视图 | +| [`Clear`](clear.md) | 清除 | +| [`GetFramebuffer`](get-framebuffer.md) | 获取帧缓冲 | +| [`GetTexture`](get-texture.md) | 获取纹理 | +| [`GetMipLevel`](get-mip-level.md) | 获取 Mip 级别 | +| [`GetWidth`](get-size.md) | 获取宽度 | +| [`GetHeight`](get-size.md) | 获取高度 | +| [`BindFramebuffer`](bind-framebuffer.md) | 绑定帧缓冲 | +| [`UnbindFramebuffer`](unbind-framebuffer.md) | 解绑帧缓冲 | + +## 相关文档 + +- [OpenGL 后端总览](../overview.md) diff --git a/docs/api/rhi/opengl/render-target-view/shutdown.md b/docs/api/rhi/opengl/render-target-view/shutdown.md new file mode 100644 index 0000000..46cfebd --- /dev/null +++ b/docs/api/rhi/opengl/render-target-view/shutdown.md @@ -0,0 +1,11 @@ +# OpenGLRenderTargetView::Shutdown + +```cpp +void Shutdown(); +``` + +关闭渲染目标视图。 + +## 相关文档 + +- [OpenGLRenderTargetView 总览](render-target-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/render-target-view/unbind-framebuffer.md b/docs/api/rhi/opengl/render-target-view/unbind-framebuffer.md new file mode 100644 index 0000000..b90f020 --- /dev/null +++ b/docs/api/rhi/opengl/render-target-view/unbind-framebuffer.md @@ -0,0 +1,17 @@ +# OpenGLRenderTargetView::UnbindFramebuffer + +```cpp +static void UnbindFramebuffer() +``` + +静态方法,解除当前渲染目标帧缓冲区的绑定。 + +**示例:** + +```cpp +OpenGLRenderTargetView::UnbindFramebuffer(); +``` + +## 相关文档 + +- [OpenGLRenderTargetView](render-target-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/render-target-view/unbind.md b/docs/api/rhi/opengl/render-target-view/unbind.md new file mode 100644 index 0000000..425460f --- /dev/null +++ b/docs/api/rhi/opengl/render-target-view/unbind.md @@ -0,0 +1,11 @@ +# OpenGLRenderTargetView::Unbind + +```cpp +void Unbind() const; +``` + +解除绑定渲染目标视图。 + +## 相关文档 + +- [OpenGLRenderTargetView 总览](render-target-view.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/sampler/bind.md b/docs/api/rhi/opengl/sampler/bind.md new file mode 100644 index 0000000..a8d8649 --- /dev/null +++ b/docs/api/rhi/opengl/sampler/bind.md @@ -0,0 +1,22 @@ +# OpenGLSampler::Bind + +```cpp +void Bind(unsigned int unit); +``` + +绑定采样器到纹理单元。 + +**参数:** +- `unit` - 纹理单元编号 + +**复杂度:** O(1) + +**示例:** + +```cpp +sampler.Bind(0); +``` + +## 相关文档 + +- [OpenGLSampler 总览](sampler.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/sampler/get-id.md b/docs/api/rhi/opengl/sampler/get-id.md new file mode 100644 index 0000000..8034084 --- /dev/null +++ b/docs/api/rhi/opengl/sampler/get-id.md @@ -0,0 +1,21 @@ +# OpenGLSampler::GetID + +```cpp +unsigned int GetID() const +unsigned int GetID() override +``` + +获取 OpenGL 采样器对象 ID。 + +**返回:** `unsigned int` - 采样器 ID + +**示例:** + +```cpp +unsigned int samplerID = sampler.GetID(); +glBindSampler(0, samplerID); +``` + +## 相关文档 + +- [OpenGLSampler](sampler.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/sampler/initialize.md b/docs/api/rhi/opengl/sampler/initialize.md new file mode 100644 index 0000000..59be4c5 --- /dev/null +++ b/docs/api/rhi/opengl/sampler/initialize.md @@ -0,0 +1,29 @@ +# OpenGLSampler::Initialize + +```cpp +bool Initialize(const OpenGLSamplerDesc& desc); +``` + +初始化采样器。 + +**参数:** +- `desc` - 采样器描述符 + +**返回:** 成功返回 `true`,失败返回 `false` + +**复杂度:** O(1) + +**示例:** + +```cpp +OpenGLSamplerDesc desc; +desc.minFilter = SamplerFilter::LinearMipmapLinear; +desc.magFilter = SamplerFilter::Linear; +desc.wrapS = SamplerWrapMode::Repeat; +desc.wrapT = SamplerWrapMode::Repeat; +sampler.Initialize(desc); +``` + +## 相关文档 + +- [OpenGLSampler 总览](sampler.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/sampler/sampler.md b/docs/api/rhi/opengl/sampler/sampler.md new file mode 100644 index 0000000..e90b9cb --- /dev/null +++ b/docs/api/rhi/opengl/sampler/sampler.md @@ -0,0 +1,21 @@ +# OpenGLSampler + +**命名空间**: `XCEngine::RHI` + +**描述**: OpenGL 采样器实现,继承自 `RHISampler`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](initialize.md) | 初始化采样器 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭采样器 | +| [`Bind`](bind.md) | 绑定采样器 | +| [`Unbind`](unbind.md) | 解绑采样器 | +| [`GetID`](get-id.md) | 获取采样器 ID | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | + +## 相关文档 + +- [OpenGL 后端总览](../overview.md) +- [RHISampler](../../sampler/sampler.md) - 抽象采样器接口 diff --git a/docs/api/rhi/opengl/sampler/unbind.md b/docs/api/rhi/opengl/sampler/unbind.md new file mode 100644 index 0000000..d7263d6 --- /dev/null +++ b/docs/api/rhi/opengl/sampler/unbind.md @@ -0,0 +1,22 @@ +# OpenGLSampler::Unbind + +```cpp +void Unbind(unsigned int unit); +``` + +解绑采样器。 + +**参数:** +- `unit` - 纹理单元编号 + +**复杂度:** O(1) + +**示例:** + +```cpp +sampler.Unbind(0); +``` + +## 相关文档 + +- [OpenGLSampler 总览](sampler.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/shader/compile-compute.md b/docs/api/rhi/opengl/shader/compile-compute.md new file mode 100644 index 0000000..f5d05cd --- /dev/null +++ b/docs/api/rhi/opengl/shader/compile-compute.md @@ -0,0 +1,30 @@ +# OpenGLShader::CompileCompute + +```cpp +bool CompileCompute(const char* computeSource); +``` + +从源代码编译计算着色器。 + +**参数:** +- `computeSource` - 计算着色器源代码 + +**返回:** 成功返回 `true`,失败返回 `false` + +**线程安全:** ❌ + +**示例:** + +```cpp +const char* cs = R"( + #version 430 core + layout(local_size_x = 16, local_size_y = 16) in; + void main() { /* compute logic */ } +)"; +shader->CompileCompute(cs); +``` + +## 相关文档 + +- [OpenGLShader 总览](shader.md) - 返回类总览 +- [Compile (VS+FS)](compile-vs-fs.md) - 图形着色器版本 diff --git a/docs/api/rhi/opengl/shader/compile-from-file-vs-fs.md b/docs/api/rhi/opengl/shader/compile-from-file-vs-fs.md new file mode 100644 index 0000000..7ed115a --- /dev/null +++ b/docs/api/rhi/opengl/shader/compile-from-file-vs-fs.md @@ -0,0 +1,25 @@ +# OpenGLShader::CompileFromFile (VS+FS) + +```cpp +bool CompileFromFile(const char* vertexPath, const char* fragmentPath); +``` + +从文件编译顶点着色器和片段着色器。 + +**参数:** +- `vertexPath` - 顶点着色器文件路径 +- `fragmentPath` - 片段着色器文件路径 + +**返回:** 成功返回 `true`,失败返回 `false` + +**示例:** + +```cpp +shader->CompileFromFile("shaders/vertex.glsl", "shaders/fragment.glsl"); +shader->Use(); +``` + +## 相关文档 + +- [OpenGLShader 总览](shader.md) - 返回类总览 +- [CompileFromFile (VS+GS+FS)](compile-from-file-vs-gs-fs.md) - 带几何着色器版本 diff --git a/docs/api/rhi/opengl/shader/compile-from-file-vs-gs-fs.md b/docs/api/rhi/opengl/shader/compile-from-file-vs-gs-fs.md new file mode 100644 index 0000000..b79c517 --- /dev/null +++ b/docs/api/rhi/opengl/shader/compile-from-file-vs-gs-fs.md @@ -0,0 +1,26 @@ +# OpenGLShader::CompileFromFile (VS+GS+FS) + +```cpp +bool CompileFromFile(const char* vertexPath, const char* fragmentPath, const char* geometryPath); +``` + +从文件编译顶点着色器、几何着色器和片段着色器。 + +**参数:** +- `vertexPath` - 顶点着色器文件路径 +- `fragmentPath` - 片段着色器文件路径 +- `geometryPath` - 几何着色器文件路径 + +**返回:** 成功返回 `true`,失败返回 `false` + +**示例:** + +```cpp +shader->CompileFromFile("shaders/vertex.glsl", "shaders/fragment.glsl", "shaders/geometry.glsl"); +shader->Use(); +``` + +## 相关文档 + +- [OpenGLShader 总览](shader.md) - 返回类总览 +- [CompileFromFile (VS+FS)](compile-from-file-vs-fs.md) - 不带几何着色器版本 diff --git a/docs/api/rhi/opengl/shader/compile-vs-fs.md b/docs/api/rhi/opengl/shader/compile-vs-fs.md new file mode 100644 index 0000000..8aa96f4 --- /dev/null +++ b/docs/api/rhi/opengl/shader/compile-vs-fs.md @@ -0,0 +1,34 @@ +# OpenGLShader::Compile (VS+FS) + +```cpp +bool Compile(const char* vertexSource, const char* fragmentSource); +``` + +从源代码编译顶点着色器和片段着色器。 + +**参数:** +- `vertexSource` - 顶点着色器源代码 +- `fragmentSource` - 片段着色器源代码 + +**返回:** 成功返回 `true`,失败返回 `false` + +**示例:** + +```cpp +const char* vs = R"( + #version 330 core + void main() { gl_Position = vec4(0.0); } +)"; +const char* fs = R"( + #version 330 core + out vec4 color; + void main() { color = vec4(1.0); } +)"; +shader->Compile(vs, fs); +shader->Use(); +``` + +## 相关文档 + +- [OpenGLShader 总览](shader.md) - 返回类总览 +- [CompileCompute](compile-compute.md) - 计算着色器版本 diff --git a/docs/api/rhi/opengl/shader/get-id.md b/docs/api/rhi/opengl/shader/get-id.md new file mode 100644 index 0000000..6b8bfb6 --- /dev/null +++ b/docs/api/rhi/opengl/shader/get-id.md @@ -0,0 +1,23 @@ +# OpenGLShader::GetID + +```cpp +unsigned int GetID() const; +``` + +获取 OpenGL 着色器程序 ID。 + +**返回:** OpenGL 程序对象 ID + +**线程安全:** ❌ + +**示例:** + +```cpp +unsigned int programId = shader->GetID(); +glUseProgram(programId); +``` + +## 相关文档 + +- [OpenGLShader 总览](shader.md) - 返回类总览 +- [GetNativeHandle](../../buffer/get-native-handle.md) - 原生句柄 diff --git a/docs/api/rhi/opengl/shader/get-uniform-location.md b/docs/api/rhi/opengl/shader/get-uniform-location.md new file mode 100644 index 0000000..aa658d0 --- /dev/null +++ b/docs/api/rhi/opengl/shader/get-uniform-location.md @@ -0,0 +1,27 @@ +# OpenGLShader::GetUniformLocation + +```cpp +int GetUniformLocation(const char* name) const; +``` + +获取 Uniform 变量的位置索引。 + +**参数:** +- `name` - Uniform 变量名称 + +**返回:** Uniform 位置索引,失败返回 -1 + +**线程安全:** ❌ + +**示例:** + +```cpp +int loc = shader->GetUniformLocation("modelMatrix"); +if (loc != -1) { + glUniformMatrix4fv(loc, 1, GL_FALSE, &modelMatrix[0][0]); +} +``` + +## 相关文档 + +- [OpenGLShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/shader/set-float-array.md b/docs/api/rhi/opengl/shader/set-float-array.md new file mode 100644 index 0000000..4852a20 --- /dev/null +++ b/docs/api/rhi/opengl/shader/set-float-array.md @@ -0,0 +1,26 @@ +# OpenGLShader::SetFloatArray + +```cpp +void SetFloatArray(const char* name, const float* values, unsigned int count); +``` + +设置浮点数数组 Uniform 变量。 + +**参数:** +- `name` - Uniform 变量名称 +- `values` - 浮点数数组指针 +- `count` - 数组元素数量 + +**线程安全:** ❌ + +**示例:** + +```cpp +float weights[] = { 0.25f, 0.25f, 0.25f, 0.25f }; +shader->SetFloatArray("vertexWeights", weights, 4); +``` + +## 相关文档 + +- [OpenGLShader 总览](shader.md) - 返回类总览 +- [SetFloat](../../shader/set-float.md) - 单个浮点数版本 diff --git a/docs/api/rhi/opengl/shader/set-int-array.md b/docs/api/rhi/opengl/shader/set-int-array.md new file mode 100644 index 0000000..600f662 --- /dev/null +++ b/docs/api/rhi/opengl/shader/set-int-array.md @@ -0,0 +1,26 @@ +# OpenGLShader::SetIntArray + +```cpp +void SetIntArray(const char* name, const int* values, unsigned int count); +``` + +设置整数数组 Uniform 变量。 + +**参数:** +- `name` - Uniform 变量名称 +- `values` - 整数数组指针 +- `count` - 数组元素数量 + +**线程安全:** ❌ + +**示例:** + +```cpp +int indices[] = { 0, 1, 2, 3 }; +shader->SetIntArray("boneIndices", indices, 4); +``` + +## 相关文档 + +- [OpenGLShader 总览](shader.md) - 返回类总览 +- [SetInt](../../shader/set-int.md) - 单个整数版本 diff --git a/docs/api/rhi/opengl/shader/shader.md b/docs/api/rhi/opengl/shader/shader.md new file mode 100644 index 0000000..0e2dd21 --- /dev/null +++ b/docs/api/rhi/opengl/shader/shader.md @@ -0,0 +1,33 @@ +# OpenGLShader + +**命名空间**: `XCEngine::RHI` + +**描述**: OpenGL 着色器实现,继承自 `RHIShader`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`CompileFromFile`](../../shader/compile-from-file.md) | 从文件编译着色器 | +| [`Compile`](../../shader/compile.md) | 从源码编译着色器 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭着色器 | +| [`Use`](use.md) | 使用着色器 | +| [`Bind`](../../shader/bind.md) | 绑定着色器 | +| [`Unbind`](../../shader/unbind.md) | 解绑着色器 | +| [`SetInt`](../../shader/set-int.md) | 设置整数 uniform | +| [`SetIntArray`](set-int-array.md) | 设置整数数组 uniform | +| [`SetFloat`](../../shader/set-float.md) | 设置浮点数 uniform | +| [`SetFloatArray`](set-float-array.md) | 设置浮点数数组 uniform | +| [`SetVec3`](../../shader/set-vec3.md) | 设置 vec3 uniform | +| [`SetVec4`](../../shader/set-vec4.md) | 设置 vec4 uniform | +| [`SetMat4`](../../shader/set-mat4.md) | 设置 mat4 uniform | +| [`GetUniformLocation`](get-uniform-location.md) | 获取 uniform 位置 | +| [`GetID`](get-id.md) | 获取着色器 ID | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | +| [`IsValid`](../../shader/is-valid.md) | 检查是否有效 | +| [`GetType`](../../command-queue/get-type.md) | 获取着色器类型 | + +## 相关文档 + +- [OpenGL 后端总览](../overview.md) +- [RHIShader](../../shader/shader.md) - 抽象着色器接口 diff --git a/docs/api/rhi/opengl/shader/use.md b/docs/api/rhi/opengl/shader/use.md new file mode 100644 index 0000000..91d4b18 --- /dev/null +++ b/docs/api/rhi/opengl/shader/use.md @@ -0,0 +1,21 @@ +# OpenGLShader::Use + +```cpp +void Use() const; +``` + +激活并使用当前着色器程序。 + +**线程安全:** ❌ + +**示例:** + +```cpp +shader->Use(); +// 渲染操作使用此着色器 +``` + +## 相关文档 + +- [OpenGLShader 总览](shader.md) - 返回类总览 +- [Bind/Unbind](../../shader/bind.md) - 基类绑定接口 diff --git a/docs/api/rhi/opengl/swap-chain/get-framebuffer-size.md b/docs/api/rhi/opengl/swap-chain/get-framebuffer-size.md new file mode 100644 index 0000000..871a798 --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/get-framebuffer-size.md @@ -0,0 +1,23 @@ +# OpenGLSwapChain::SetFramebufferSize + +```cpp +void SetFramebufferSize(int width, int height); +``` + +设置帧缓冲区大小。 + +**参数:** +- `width` - 帧缓冲区宽度 +- `height` - 帧缓冲区高度 + +**线程安全:** ❌ + +**示例:** + +```cpp +swapChain->SetFramebufferSize(1920, 1080); +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/swap-chain/get-size.md b/docs/api/rhi/opengl/swap-chain/get-size.md new file mode 100644 index 0000000..6671d16 --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/get-size.md @@ -0,0 +1,21 @@ +# OpenGLSwapChain::GetWidth / GetHeight + +```cpp +int GetWidth() const; +int GetHeight() const; +``` + +获取交换链的宽度和高度。 + +**返回:** 宽度/高度(像素) + +**示例:** + +```cpp +int width = swapChain->GetWidth(); +int height = swapChain->GetHeight(); +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/swap-chain/get-window.md b/docs/api/rhi/opengl/swap-chain/get-window.md new file mode 100644 index 0000000..3014baf --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/get-window.md @@ -0,0 +1,22 @@ +# OpenGLSwapChain::GetWindow + +```cpp +GLFWwindow* GetWindow() const; +``` + +获取关联的 GLFW 窗口指针。 + +**返回:** GLFW 窗口指针 + +**线程安全:** ❌ + +**示例:** + +```cpp +GLFWwindow* window = swapChain->GetWindow(); +glfwSetWindowTitle(window, "New Title"); +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/swap-chain/initialize-mode.md b/docs/api/rhi/opengl/swap-chain/initialize-mode.md new file mode 100644 index 0000000..96b9fa6 --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/initialize-mode.md @@ -0,0 +1,25 @@ +# OpenGLSwapChain::Initialize (mode) + +```cpp +bool Initialize(GLFWwindow* window, int width, int height, PresentMode mode = PresentMode::VSync); +``` + +使用指定显示模式初始化交换链。 + +**参数:** +- `window` - GLFW 窗口指针 +- `width` - 交换链宽度 +- `height` - 交换链高度 +- `mode` - 呈现模式(默认 VSync) + +**返回:** 成功返回 `true`,失败返回 `false` + +**示例:** + +```cpp +swapChain->Initialize(window, 1920, 1080, PresentMode::VSync); +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/swap-chain/initialize.md b/docs/api/rhi/opengl/swap-chain/initialize.md new file mode 100644 index 0000000..bd19bed --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/initialize.md @@ -0,0 +1,24 @@ +# OpenGLSwapChain::Initialize + +```cpp +bool Initialize(GLFWwindow* window, bool vsync = true); +``` + +初始化 OpenGL 交换链。 + +**参数:** +- `window` - GLFW 窗口指针 +- `vsync` - 是否启用垂直同步 + +**返回:** 成功返回 true + +**示例:** + +```cpp +OpenGLSwapChain swapChain; +swapChain.Initialize(window, true); +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/swap-chain/is-fullscreen.md b/docs/api/rhi/opengl/swap-chain/is-fullscreen.md new file mode 100644 index 0000000..73b7059 --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/is-fullscreen.md @@ -0,0 +1,24 @@ +# OpenGLSwapChain::IsFullscreen + +```cpp +bool IsFullscreen() const; +``` + +查询是否处于全屏模式。 + +**返回:** `true` 表示全屏模式,`false` 表示窗口模式 + +**线程安全:** ❌ + +**示例:** + +```cpp +if (swapChain->IsFullscreen()) { + // 全屏模式 +} +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 +- [SetFullscreen](set-fullscreen.md) - 设置全屏模式 diff --git a/docs/api/rhi/opengl/swap-chain/is-vsync.md b/docs/api/rhi/opengl/swap-chain/is-vsync.md new file mode 100644 index 0000000..8182a60 --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/is-vsync.md @@ -0,0 +1,24 @@ +# OpenGLSwapChain::IsVSync + +```cpp +bool IsVSync() const; +``` + +查询垂直同步是否启用。 + +**返回:** `true` 表示启用垂直同步,`false` 表示禁用 + +**线程安全:** ❌ + +**示例:** + +```cpp +if (swapChain->IsVSync()) { + // 垂直同步已启用 +} +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 +- [SetVSync](set-vsync.md) - 设置垂直同步 diff --git a/docs/api/rhi/opengl/swap-chain/poll-events.md b/docs/api/rhi/opengl/swap-chain/poll-events.md new file mode 100644 index 0000000..caa6ba4 --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/poll-events.md @@ -0,0 +1,22 @@ +# OpenGLSwapChain::PollEvents + +```cpp +void PollEvents(); +``` + +处理所有待处理的窗口事件。 + +**线程安全:** ❌ + +**示例:** + +```cpp +while (!swapChain->ShouldClose()) { + swapChain->PollEvents(); + // 渲染逻辑 +} +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/swap-chain/present.md b/docs/api/rhi/opengl/swap-chain/present.md new file mode 100644 index 0000000..4eb86fa --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/present.md @@ -0,0 +1,24 @@ +# OpenGLSwapChain::Present + +```cpp +void Present(uint32_t syncInterval = 1, uint32_t flags = 0); +``` + +呈现渲染结果到屏幕。 + +**参数:** +- `syncInterval` - 垂直同步间隔(0=立即,1+=等待垂直同步) +- `flags` - 呈现标志 + +**线程安全:** ❌ + +**示例:** + +```cpp +swapChain->Present(1, 0); +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 +- [SwapBuffers](swap-buffers.md) - 直接交换缓冲区 diff --git a/docs/api/rhi/opengl/swap-chain/set-fullscreen.md b/docs/api/rhi/opengl/swap-chain/set-fullscreen.md new file mode 100644 index 0000000..92ef573 --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/set-fullscreen.md @@ -0,0 +1,23 @@ +# OpenGLSwapChain::SetFullscreen + +```cpp +void SetFullscreen(bool fullscreen); +``` + +设置全屏模式。 + +**参数:** +- `fullscreen` - 是否切换到全屏模式 + +**线程安全:** ❌ + +**示例:** + +```cpp +swapChain->SetFullscreen(true); +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 +- [IsFullscreen](is-fullscreen.md) - 查询全屏状态 diff --git a/docs/api/rhi/opengl/swap-chain/set-should-close.md b/docs/api/rhi/opengl/swap-chain/set-should-close.md new file mode 100644 index 0000000..ccfd331 --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/set-should-close.md @@ -0,0 +1,23 @@ +# OpenGLSwapChain::SetShouldClose + +```cpp +void SetShouldClose(bool shouldClose); +``` + +设置窗口关闭标志。 + +**参数:** +- `shouldClose` - 是否应该关闭 + +**线程安全:** ❌ + +**示例:** + +```cpp +swapChain->SetShouldClose(true); +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 +- [ShouldClose](should-close.md) - 查询关闭标志 diff --git a/docs/api/rhi/opengl/swap-chain/set-vsync.md b/docs/api/rhi/opengl/swap-chain/set-vsync.md new file mode 100644 index 0000000..9c87226 --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/set-vsync.md @@ -0,0 +1,23 @@ +# OpenGLSwapChain::SetVSync + +```cpp +void SetVSync(bool enabled); +``` + +设置垂直同步开关。 + +**参数:** +- `enabled` - 是否启用垂直同步 + +**线程安全:** ❌ + +**示例:** + +```cpp +swapChain->SetVSync(true); +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 +- [IsVSync](is-vsync.md) - 查询垂直同步状态 diff --git a/docs/api/rhi/opengl/swap-chain/should-close.md b/docs/api/rhi/opengl/swap-chain/should-close.md new file mode 100644 index 0000000..2ba2d56 --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/should-close.md @@ -0,0 +1,25 @@ +# OpenGLSwapChain::ShouldClose + +```cpp +bool ShouldClose() const; +``` + +查询窗口是否应该关闭。 + +**返回:** `true` 表示应该关闭,`false` 表示继续运行 + +**线程安全:** ❌ + +**示例:** + +```cpp +while (!swapChain->ShouldClose()) { + swapChain->PollEvents(); + // 渲染逻辑 +} +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 +- [SetShouldClose](set-should-close.md) - 设置关闭标志 diff --git a/docs/api/rhi/opengl/swap-chain/swap-buffers.md b/docs/api/rhi/opengl/swap-chain/swap-buffers.md new file mode 100644 index 0000000..771345b --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/swap-buffers.md @@ -0,0 +1,20 @@ +# OpenGLSwapChain::SwapBuffers + +```cpp +void SwapBuffers(); +``` + +直接交换前后缓冲区。 + +**线程安全:** ❌ + +**示例:** + +```cpp +swapChain->SwapBuffers(); +``` + +## 相关文档 + +- [OpenGLSwapChain 总览](swap-chain.md) - 返回类总览 +- [Present](present.md) - 呈现(带垂直同步) diff --git a/docs/api/rhi/opengl/swap-chain/swap-chain.md b/docs/api/rhi/opengl/swap-chain/swap-chain.md new file mode 100644 index 0000000..7ced78c --- /dev/null +++ b/docs/api/rhi/opengl/swap-chain/swap-chain.md @@ -0,0 +1,36 @@ +# OpenGLSwapChain + +**命名空间**: `XCEngine::RHI` + +**描述**: OpenGL 交换链实现,继承自 `RHISwapChain`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](initialize.md) | 初始化交换链 | +| [`InitializeMode`](initialize-mode.md) | 使用模式初始化 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭交换链 | +| [`Present`](present.md) | 呈现画面 | +| [`SwapBuffers`](swap-buffers.md) | 交换缓冲 | +| [`Resize`](../../swap-chain/resize.md) | 调整交换链大小 | +| [`SetVSync`](set-vsync.md) | 设置垂直同步 | +| [`IsVSync`](is-vsync.md) | 检查是否垂直同步 | +| [`SetFullscreen`](set-fullscreen.md) | 设置全屏模式 | +| [`IsFullscreen`](is-fullscreen.md) | 检查是否全屏 | +| [`ShouldClose`](should-close.md) | 检查是否应关闭 | +| [`SetShouldClose`](set-should-close.md) | 设置关闭标志 | +| [`PollEvents`](poll-events.md) | 处理窗口事件 | +| [`GetCurrentBackBufferIndex`](../../swap-chain/get-current-back-buffer-index.md) | 获取当前后台缓冲区索引 | +| [`GetCurrentBackBuffer`](../../swap-chain/get-current-back-buffer.md) | 获取当前后台缓冲区 | +| [`GetWidth`](get-size.md) | 获取宽度 | +| [`GetHeight`](get-size.md) | 获取高度 | +| [`GetFramebufferWidth`](get-framebuffer-size.md) | 获取帧缓冲宽度 | +| [`GetFramebufferHeight`](get-framebuffer-size.md) | 获取帧缓冲高度 | +| [`GetWindow`](get-window.md) | 获取窗口 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | + +## 相关文档 + +- [OpenGL 后端总览](../overview.md) +- [RHISwapChain](../../swap-chain/swap-chain.md) - 抽象交换链接口 diff --git a/docs/api/rhi/opengl/texture/bind-image.md b/docs/api/rhi/opengl/texture/bind-image.md new file mode 100644 index 0000000..7873961 --- /dev/null +++ b/docs/api/rhi/opengl/texture/bind-image.md @@ -0,0 +1,22 @@ +# OpenGLTexture::BindImage + +```cpp +void BindImage(int slot, bool read, bool write) const +``` + +将纹理绑定到图像单元,用于着色器图像访问。 + +**参数:** +- `slot` - 图像单元槽位 +- `read` - 是否可读 +- `write` - 是否可写 + +**示例:** + +```cpp +texture.BindImage(0, true, false); // 只读访问 +``` + +## 相关文档 + +- [OpenGLTexture](texture.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/texture/generate-mipmap.md b/docs/api/rhi/opengl/texture/generate-mipmap.md new file mode 100644 index 0000000..b7126d0 --- /dev/null +++ b/docs/api/rhi/opengl/texture/generate-mipmap.md @@ -0,0 +1,18 @@ +# OpenGLTexture::GenerateMipmap + +```cpp +void GenerateMipmap() +``` + +生成纹理的 mipmap。 + +**示例:** + +```cpp +texture.LoadFromFile("assets/textures/wood.jpg"); +texture.GenerateMipmap(); +``` + +## 相关文档 + +- [OpenGLTexture](texture.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/texture/get-id.md b/docs/api/rhi/opengl/texture/get-id.md new file mode 100644 index 0000000..b43ecb9 --- /dev/null +++ b/docs/api/rhi/opengl/texture/get-id.md @@ -0,0 +1,20 @@ +# OpenGLTexture::GetID + +```cpp +unsigned int GetID() const +``` + +获取 OpenGL 纹理对象 ID。 + +**返回:** `unsigned int` - OpenGL 纹理 ID + +**示例:** + +```cpp +unsigned int texID = texture.GetID(); +glBindTexture(GL_TEXTURE_2D, texID); +``` + +## 相关文档 + +- [OpenGLTexture](texture.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/texture/get-opengl-type.md b/docs/api/rhi/opengl/texture/get-opengl-type.md new file mode 100644 index 0000000..f9dcf68 --- /dev/null +++ b/docs/api/rhi/opengl/texture/get-opengl-type.md @@ -0,0 +1,23 @@ +# OpenGLTexture::GetOpenGLType + +```cpp +OpenGLTextureType GetOpenGLType() const +``` + +获取纹理的 OpenGL 类型。 + +**返回:** `OpenGLTextureType` - 纹理类型枚举值: +- `OpenGLTextureType::Texture1D` +- `OpenGLTextureType::Texture2D` +- `OpenGLTextureType::TextureCube` +- 等等 + +**示例:** + +```cpp +OpenGLTextureType type = texture.GetOpenGLType(); +``` + +## 相关文档 + +- [OpenGLTexture](texture.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/texture/initialize-2d.md b/docs/api/rhi/opengl/texture/initialize-2d.md new file mode 100644 index 0000000..14c1a66 --- /dev/null +++ b/docs/api/rhi/opengl/texture/initialize-2d.md @@ -0,0 +1,28 @@ +# OpenGLTexture::Initialize2D + +```cpp +bool Initialize2D(int width, int height, int channels, const void* data, bool generateMipmap = true) +``` + +初始化一个 2D 纹理。 + +**参数:** +- `width` - 纹理宽度(像素) +- `height` - 纹理高度(像素) +- `channels` - 通道数(1=R, 2=RG, 4=RGBA) +- `data` - 纹理数据指针(可以为 nullptr 创建空纹理) +- `generateMipmap` - 是否自动生成 mipmap(默认为 true) + +**返回:** `bool` - 成功返回 true,失败返回 false + +**示例:** + +```cpp +OpenGLTexture texture; +std::vector pixels(width * height * 4); +texture.Initialize2D(width, height, 4, pixels.data(), true); +``` + +## 相关文档 + +- [OpenGLTexture](texture.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/texture/initialize-cube-map.md b/docs/api/rhi/opengl/texture/initialize-cube-map.md new file mode 100644 index 0000000..0a5242f --- /dev/null +++ b/docs/api/rhi/opengl/texture/initialize-cube-map.md @@ -0,0 +1,26 @@ +# OpenGLTexture::InitializeCubeMap + +```cpp +bool InitializeCubeMap(int size, int mipLevels, OpenGLFormat format, const void* data = nullptr) +``` + +初始化一个立方体纹理。 + +**参数:** +- `size` - 立方体贴面的边长 +- `mipLevels` - mipmap 级别数量 +- `format` - 纹理格式(OpenGLFormat 枚举值) +- `data` - 纹理数据指针(可以为 nullptr) + +**返回:** `bool` - 成功返回 true,失败返回 false + +**示例:** + +```cpp +OpenGLTexture cubemap; +cubemap.InitializeCubeMap(512, 1, OpenGLFormat::RGBA8, nullptr); +``` + +## 相关文档 + +- [OpenGLTexture](texture.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/texture/load-from-file.md b/docs/api/rhi/opengl/texture/load-from-file.md new file mode 100644 index 0000000..be55ffc --- /dev/null +++ b/docs/api/rhi/opengl/texture/load-from-file.md @@ -0,0 +1,26 @@ +# OpenGLTexture::LoadFromFile + +```cpp +bool LoadFromFile(const char* path, bool flipVertical = true) +``` + +从图像文件加载纹理。 + +**参数:** +- `path` - 图像文件路径 +- `flipVertical` - 是否垂直翻转图像(默认为 true) + +**返回:** `bool` - 成功返回 true,失败返回 false + +**示例:** + +```cpp +OpenGLTexture texture; +if (texture.LoadFromFile("assets/textures/brick.jpg", true)) { + texture.GenerateMipmap(); +} +``` + +## 相关文档 + +- [OpenGLTexture](texture.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/texture/set-filtering.md b/docs/api/rhi/opengl/texture/set-filtering.md new file mode 100644 index 0000000..50f91f9 --- /dev/null +++ b/docs/api/rhi/opengl/texture/set-filtering.md @@ -0,0 +1,21 @@ +# OpenGLTexture::SetFiltering + +```cpp +void SetFiltering(int minFilter, int magFilter) +``` + +设置纹理过滤模式。 + +**参数:** +- `minFilter` - 缩小过滤模式(GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST 等) +- `magFilter` - 放大过滤模式(GL_NEAREST, GL_LINEAR) + +**示例:** + +```cpp +texture.SetFiltering(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR); +``` + +## 相关文档 + +- [OpenGLTexture](texture.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/texture/set-wrapping.md b/docs/api/rhi/opengl/texture/set-wrapping.md new file mode 100644 index 0000000..879307c --- /dev/null +++ b/docs/api/rhi/opengl/texture/set-wrapping.md @@ -0,0 +1,22 @@ +# OpenGLTexture::SetWrapping + +```cpp +void SetWrapping(int wrapS, int wrapT, int wrapR = -1) +``` + +设置纹理环绕模式。 + +**参数:** +- `wrapS` - S 轴环绕模式(GL_REPEAT, GL_CLAMP_TO_EDGE 等) +- `wrapT` - T 轴环绕模式 +- `wrapR` - R 轴环绕模式(默认为 -1,表示与 wrapT 相同) + +**示例:** + +```cpp +texture.SetWrapping(GL_REPEAT, GL_REPEAT, GL_REPEAT); +``` + +## 相关文档 + +- [OpenGLTexture](texture.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/texture/texture.md b/docs/api/rhi/opengl/texture/texture.md new file mode 100644 index 0000000..597946b --- /dev/null +++ b/docs/api/rhi/opengl/texture/texture.md @@ -0,0 +1,39 @@ +# OpenGLTexture + +**命名空间**: `XCEngine::RHI` + +**描述**: OpenGL 纹理的实现,继承自 `RHITexture`。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](initialize-2d.md) | 初始化 2D 纹理 | +| [`Initialize2D`](initialize-2d.md) | 初始化 2D 纹理 | +| [`InitializeCubeMap`](initialize-cube-map.md) | 初始化立方体贴图 | +| [`LoadFromFile`](load-from-file.md) | 从文件加载纹理 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭纹理 | +| [`Bind`](bind-image.md) | 绑定纹理 | +| [`Unbind`](../../shader/unbind.md) | 解绑纹理 | +| [`BindImage`](bind-image.md) | 绑定图像 | +| [`GenerateMipmap`](generate-mipmap.md) | 生成多级渐远纹理 | +| [`SetFiltering`](set-filtering.md) | 设置过滤模式 | +| [`SetWrapping`](set-wrapping.md) | 设置环绕模式 | +| [`GetID`](get-id.md) | 获取 OpenGL 纹理 ID | +| [`GetOpenGLType`](get-opengl-type.md) | 获取 OpenGL 纹理类型 | +| [`GetWidth`](../../texture/get-width.md) | 获取纹理宽度 | +| [`GetHeight`](../../texture/get-height.md) | 获取纹理高度 | +| [`GetDepth`](../../texture/get-depth.md) | 获取纹理深度 | +| [`GetMipLevels`](../../texture/get-mip-levels.md) | 获取 Mip 级别 | +| [`GetTextureType`](../../texture/get-texture-type.md) | 获取纹理类型 | +| [`GetNativeHandle`](../../buffer/get-native-handle.md) | 获取原生句柄 | +| [`GetState`](../../buffer/get-state.md) | 获取资源状态 | +| [`SetState`](../../buffer/set-state.md) | 设置资源状态 | +| [`GetName`](../../buffer/get-name.md) | 获取资源名称 | +| [`SetName`](../../buffer/set-name.md) | 设置资源名称 | +| [`GetFormat`](../../texture/get-format.md) | 获取纹理格式 | + +## 相关文档 + +- [OpenGL 后端总览](../overview.md) +- [RHITexture](../../texture/texture.md) - 抽象纹理接口 diff --git a/docs/api/rhi/opengl/vertex-array/add-vertex-buffer.md b/docs/api/rhi/opengl/vertex-array/add-vertex-buffer.md new file mode 100644 index 0000000..5af59a0 --- /dev/null +++ b/docs/api/rhi/opengl/vertex-array/add-vertex-buffer.md @@ -0,0 +1,28 @@ +# OpenGLVertexArray::AddVertexBuffer + +```cpp +void AddVertexBuffer(unsigned int buffer, const VertexAttribute& attribute) +``` + +添加顶点缓冲区并指定顶点属性。 + +**参数:** +- `buffer` - OpenGL 缓冲区对象 ID +- `attribute` - 顶点属性描述结构体 + +**示例:** + +```cpp +VertexAttribute attr; +attr.index = 0; +attr.count = 3; +attr.type = GL_FLOAT; +attr.normalized = GL_FALSE; +attr.stride = sizeof(Vertex); +attr.offset = 0; +vao.AddVertexBuffer(vbo, attr); +``` + +## 相关文档 + +- [OpenGLVertexArray](vertex-array.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/vertex-array/get-id.md b/docs/api/rhi/opengl/vertex-array/get-id.md new file mode 100644 index 0000000..b391419 --- /dev/null +++ b/docs/api/rhi/opengl/vertex-array/get-id.md @@ -0,0 +1,20 @@ +# OpenGLVertexArray::GetID + +```cpp +unsigned int GetID() const +``` + +获取 OpenGL 顶点数组对象 ID。 + +**返回:** `unsigned int` - VAO ID + +**示例:** + +```cpp +unsigned int vaoID = vao.GetID(); +glBindVertexArray(vaoID); +``` + +## 相关文档 + +- [OpenGLVertexArray](vertex-array.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/vertex-array/get-index-buffer.md b/docs/api/rhi/opengl/vertex-array/get-index-buffer.md new file mode 100644 index 0000000..9f2615d --- /dev/null +++ b/docs/api/rhi/opengl/vertex-array/get-index-buffer.md @@ -0,0 +1,19 @@ +# OpenGLVertexArray::GetIndexBuffer + +```cpp +unsigned int GetIndexBuffer() const +``` + +获取索引缓冲区 ID。 + +**返回:** `unsigned int` - 索引缓冲区 ID + +**示例:** + +```cpp +unsigned int ibo = vao.GetIndexBuffer(); +``` + +## 相关文档 + +- [OpenGLVertexArray](vertex-array.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/vertex-array/get-index-count.md b/docs/api/rhi/opengl/vertex-array/get-index-count.md new file mode 100644 index 0000000..14b5ec7 --- /dev/null +++ b/docs/api/rhi/opengl/vertex-array/get-index-count.md @@ -0,0 +1,20 @@ +# OpenGLVertexArray::GetIndexCount + +```cpp +unsigned int GetIndexCount() const +``` + +获取索引数量。 + +**返回:** `unsigned int` - 索引数量 + +**示例:** + +```cpp +unsigned int count = vao.GetIndexCount(); +glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0); +``` + +## 相关文档 + +- [OpenGLVertexArray](vertex-array.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/vertex-array/set-index-buffer.md b/docs/api/rhi/opengl/vertex-array/set-index-buffer.md new file mode 100644 index 0000000..866316b --- /dev/null +++ b/docs/api/rhi/opengl/vertex-array/set-index-buffer.md @@ -0,0 +1,21 @@ +# OpenGLVertexArray::SetIndexBuffer + +```cpp +void SetIndexBuffer(unsigned int buffer, unsigned int type) +``` + +设置索引缓冲区。 + +**参数:** +- `buffer` - OpenGL 缓冲区对象 ID +- `type` - 索引数据类型(GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT) + +**示例:** + +```cpp +vao.SetIndexBuffer(ibo, GL_UNSIGNED_INT); +``` + +## 相关文档 + +- [OpenGLVertexArray](vertex-array.md) - 返回类总览 diff --git a/docs/api/rhi/opengl/vertex-array/vertex-array.md b/docs/api/rhi/opengl/vertex-array/vertex-array.md new file mode 100644 index 0000000..ecbcbce --- /dev/null +++ b/docs/api/rhi/opengl/vertex-array/vertex-array.md @@ -0,0 +1,23 @@ +# OpenGLVertexArray + +**命名空间**: `XCEngine::RHI` + +**描述**: OpenGL 顶点数组对象 (VAO) 封装。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](../../../threading/task-system/initialize.md) | 初始化顶点数组 | +| [`AddVertexBuffer`](add-vertex-buffer.md) | 添加顶点缓冲 | +| [`SetIndexBuffer`](set-index-buffer.md) | 设置索引缓冲 | +| [`Shutdown`](../../../threading/task-system/shutdown.md) | 关闭顶点数组 | +| [`Bind`](../../shader/bind.md) | 绑定顶点数组 | +| [`Unbind`](../../shader/unbind.md) | 解绑顶点数组 | +| [`GetID`](get-id.md) | 获取 OpenGL VAO ID | +| [`GetIndexBuffer`](get-index-buffer.md) | 获取索引缓冲 | +| [`GetIndexCount`](get-index-count.md) | 获取索引数量 | + +## 相关文档 + +- [OpenGL 后端总览](../overview.md) diff --git a/docs/api/rhi/pipeline-layout/get-native-handle.md b/docs/api/rhi/pipeline-layout/get-native-handle.md new file mode 100644 index 0000000..954d655 --- /dev/null +++ b/docs/api/rhi/pipeline-layout/get-native-handle.md @@ -0,0 +1,15 @@ +# RHIPipelineLayout::GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 + +**返回:** 原生管线布局句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIPipelineLayout 总览](pipeline-layout.md) - 返回类总览 diff --git a/docs/api/rhi/pipeline-layout/initialize.md b/docs/api/rhi/pipeline-layout/initialize.md new file mode 100644 index 0000000..85ee66b --- /dev/null +++ b/docs/api/rhi/pipeline-layout/initialize.md @@ -0,0 +1,18 @@ +# RHIPipelineLayout::Initialize + +```cpp +virtual bool Initialize(const RHIPipelineLayoutDesc& desc) = 0; +``` + +初始化管线布局。 + +**参数:** +- `desc` - 管线布局描述符 + +**返回:** 成功返回 `true`,失败返回 `false` + +**复杂度:** O(1) + +## 相关文档 + +- [RHIPipelineLayout 总览](pipeline-layout.md) - 返回类总览 diff --git a/docs/api/rhi/pipeline-layout/methods.md b/docs/api/rhi/pipeline-layout/methods.md new file mode 100644 index 0000000..b037204 --- /dev/null +++ b/docs/api/rhi/pipeline-layout/methods.md @@ -0,0 +1,25 @@ +# RHIPipelineLayout 方法 + +## Initialize + +```cpp +virtual bool Initialize(const RHIPipelineLayoutDesc& desc) = 0; +``` + +初始化管线布局。 + +## Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +释放管线布局资源。 + +## GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 diff --git a/docs/api/rhi/pipeline-layout/pipeline-layout.md b/docs/api/rhi/pipeline-layout/pipeline-layout.md new file mode 100644 index 0000000..4419530 --- /dev/null +++ b/docs/api/rhi/pipeline-layout/pipeline-layout.md @@ -0,0 +1,20 @@ +# RHIPipelineLayout + +**命名空间**: `XCEngine::RHI` + +**类型**: `class` (abstract) + +**描述**: GPU 渲染管线布局抽象接口,用于定义着色器资源的绑定布局。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Initialize`](initialize.md) | 初始化管线布局 | +| [`Shutdown`](shutdown.md) | 关闭并释放资源 | +| [`GetNativeHandle`](get-native-handle.md) | 获取原生句柄 | + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHIDevice](../device/device.md) - 创建设备 diff --git a/docs/api/rhi/pipeline-layout/shutdown.md b/docs/api/rhi/pipeline-layout/shutdown.md new file mode 100644 index 0000000..c4b2a22 --- /dev/null +++ b/docs/api/rhi/pipeline-layout/shutdown.md @@ -0,0 +1,13 @@ +# RHIPipelineLayout::Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +释放管线布局资源。 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIPipelineLayout 总览](pipeline-layout.md) - 返回类总览 diff --git a/docs/api/rhi/pipeline-state/get-native-handle.md b/docs/api/rhi/pipeline-state/get-native-handle.md new file mode 100644 index 0000000..0b543fc --- /dev/null +++ b/docs/api/rhi/pipeline-state/get-native-handle.md @@ -0,0 +1,15 @@ +# RHIPipelineState::GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 + +**返回:** 原生管线状态句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIPipelineState 总览](pipeline-state.md) - 返回类总览 diff --git a/docs/api/rhi/pipeline-state/get-type.md b/docs/api/rhi/pipeline-state/get-type.md new file mode 100644 index 0000000..a63b47e --- /dev/null +++ b/docs/api/rhi/pipeline-state/get-type.md @@ -0,0 +1,15 @@ +# RHIPipelineState::GetType + +```cpp +virtual PipelineType GetType() const = 0; +``` + +获取管线类型。 + +**返回:** 管线类型枚举值 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIPipelineState 总览](pipeline-state.md) - 返回类总览 diff --git a/docs/api/rhi/pipeline-state/methods.md b/docs/api/rhi/pipeline-state/methods.md new file mode 100644 index 0000000..c5618d6 --- /dev/null +++ b/docs/api/rhi/pipeline-state/methods.md @@ -0,0 +1,41 @@ +# RHIPipelineState 方法 + +## Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +释放管线状态对象。 + +## Bind + +```cpp +virtual void Bind() = 0; +``` + +绑定管线状态到管线。 + +## Unbind + +```cpp +virtual void Unbind() = 0; +``` + +解绑管线状态。 + +## GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 + +## GetType + +```cpp +virtual PipelineType GetType() const = 0; +``` + +获取管线类型。 diff --git a/docs/api/rhi/pipeline-state/pipeline-state.md b/docs/api/rhi/pipeline-state/pipeline-state.md new file mode 100644 index 0000000..4abd8da --- /dev/null +++ b/docs/api/rhi/pipeline-state/pipeline-state.md @@ -0,0 +1,30 @@ +# RHIPipelineState + +**命名空间**: `XCEngine::RHI` + +**类型**: `class` (abstract) + +**描述**: GPU 渲染管线状态抽象接口,封装了渲染管线的各种固定功能配置。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Shutdown`](shutdown.md) | 关闭并释放资源 | +| [`Bind`](../shader/bind.md) | 绑定管线状态 | +| [`Unbind`](../shader/unbind.md) | 解绑管线状态 | +| [`GetNativeHandle`](get-native-handle.md) | 获取原生句柄 | +| [`GetType`](get-type.md) | 获取管线类型 | + +## 管线类型 (PipelineType) + +| 枚举值 | 描述 | +|--------|------| +| `Graphics` | 图形渲染管线 | +| `Compute` | 计算管线 | +| `Raytracing` | 光线追踪管线 | + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHIDevice](../device/device.md) - 创建设备 diff --git a/docs/api/rhi/pipeline-state/shutdown.md b/docs/api/rhi/pipeline-state/shutdown.md new file mode 100644 index 0000000..551b01a --- /dev/null +++ b/docs/api/rhi/pipeline-state/shutdown.md @@ -0,0 +1,13 @@ +# RHIPipelineState::Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +释放管线状态对象资源。 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIPipelineState 总览](pipeline-state.md) - 返回类总览 diff --git a/docs/api/rhi/rhi.md b/docs/api/rhi/rhi.md new file mode 100644 index 0000000..b667787 --- /dev/null +++ b/docs/api/rhi/rhi.md @@ -0,0 +1,121 @@ +# RHI 模块 + +**命名空间**: `XCEngine::RHI` + +**描述**: RHI (Rendering Hardware Interface) 是 XCEngine 的硬件抽象层,提供统一的图形 API 接口,支持多个后端实现。 + +## 概述 + +RHI 模块将上层渲染逻辑与底层图形 API 解耦,通过抽象接口层提供对 DirectX 12、OpenGL 等图形 API 的统一访问。这种设计使得渲染代码可以在不同的图形 API 之间无缝切换,无需修改上层业务逻辑。 + +## 架构 + +``` +┌─────────────────────────────────────────────────────────┐ +│ 上层渲染代码 │ +├─────────────────────────────────────────────────────────┤ +│ RHI 抽象接口层 │ +│ (RHIDevice, RHIBuffer, RHITexture, RHICommandList...) │ +├───────────────┬─────────────────┬───────────────────────┤ +│ D3D12 后端 │ OpenGL 后端 │ Vulkan 后端 │ +│ (D3D12Device) │ (OpenGLDevice) │ (预留) │ +├───────────────┴─────────────────┴───────────────────────┤ +│ 原生图形 API (DirectX 12 / OpenGL) │ +└─────────────────────────────────────────────────────────┘ +``` + +## 后端类型 + +| 后端 | 枚举值 | 描述 | +|------|--------|------| +| DirectX 12 | `RHIType::D3D12` | DirectX 12 实现,现代 PC 游戏首选 | +| OpenGL | `RHIType::OpenGL` | OpenGL Core Profile 实现,跨平台兼容 | + +## 抽象类 + +### 核心设备 + +| 类 | 文档 | 描述 | +|----|------|------| +| [RHIDevice](device/device.md) | `RHIDevice.h` | 渲染设备抽象,代表图形适配器实例 | +| [RHIFactory](factory/factory.md) | `RHIFactory.h` | 设备工厂,用于创建不同后端的设备实例 | + +### 资源管理 + +| 类 | 文档 | 描述 | +|----|------|------| +| [RHIBuffer](buffer/buffer.md) | `RHIBuffer.h` | GPU 缓冲区资源,存储顶点、索引、常量等数据 | +| [RHITexture](texture/texture.md) | `RHITexture.h` | GPU 纹理资源,存储 1D/2D/3D 图像数据 | +| [RHIShader](shader/shader.md) | `RHIShader.h` | 着色器资源,管理顶点、像素等着色器程序 | + +### 命令执行 + +| 类 | 文档 | 描述 | +|----|------|------| +| [RHICommandList](command-list/command-list.md) | `RHICommandList.h` | 命令列表,记录 GPU 命令 | +| [RHICommandQueue](command-queue/command-queue.md) | `RHICommandQueue.h` | 命令队列,提交和执行命令列表 | +| [RHISwapChain](swap-chain/swap-chain.md) | `RHISwapChain.h` | 交换链,管理帧缓冲区和显示输出 | + +### 同步与状态 + +| 类 | 文档 | 描述 | +|----|------|------| +| [RHIFence](fence/fence.md) | `RHIFence.h` | 同步栅栏,CPU/GPU 同步原语 | +| [RHIPipelineState](pipeline-state/pipeline-state.md) | `RHIPipelineState.h` | 管线状态对象,封装渲染管线配置 | +| [RHISampler](sampler/sampler.md) | `RHISampler.h` | 纹理采样器,配置纹理过滤和寻址模式 | +| [RHIPipelineLayout](pipeline-layout/pipeline-layout.md) | `RHIPipelineLayout.h` | 管线布局,定义着色器资源绑定布局 | +| [RHIDescriptorPool](descriptor-pool/descriptor-pool.md) | `RHIDescriptorPool.h` | 描述符池,管理 GPU 描述符分配 | + +### 类型与能力 + +| 类 | 文档 | 描述 | +|----|------|------| +| [RHICapabilities](capabilities/capabilities.md) | `RHICapabilities.h` | 设备能力结构,描述支持的图形特性 | +| [RHITypes](types/types.md) | `RHITypes.h` | 类型定义,包含所有结构体描述符 | +| [RHIEnums](enums/enums.md) | `RHIEnums.h` | 枚举定义,包含所有枚举类型 | + +## 使用流程 + +```cpp +#include +#include + +using namespace XCEngine::RHI; + +// 1. 创建设备 +RHIDevice* device = RHIFactory::CreateRHIDevice(RHIType::D3D12); + +// 2. 初始化设备 +RHIDeviceDesc desc; +desc.windowHandle = hwnd; +desc.width = 1280; +desc.height = 720; +device->Initialize(desc); + +// 3. 创建资源 +RHIBuffer* vertexBuffer = device->CreateBuffer(bufferDesc); +RHITexture* texture = device->CreateTexture(textureDesc); + +// 4. 创建命令列表并录制 +RHICommandList* cmdList = device->CreateCommandList(cmdListDesc); +RHICommandQueue* cmdQueue = device->CreateCommandQueue(queueDesc); + +// 5. 渲染循环 +while (!swapChain->ShouldClose()) { + cmdQueue->ExecuteCommandLists(1, (void**)&cmdList); + swapChain->Present(); +} + +// 6. 清理 +device->Shutdown(); +delete device; +``` + +## 后端文档 + +- [D3D12 后端](opengl/overview.md) - DirectX 12 实现详情 +- [OpenGL 后端](opengl/overview.md) - OpenGL 实现详情 + +## 相关文档 + +- [RHI 模块源码](../../engine/include/XCEngine/RHI/) - 源代码位置 diff --git a/docs/api/rhi/sampler/get-id.md b/docs/api/rhi/sampler/get-id.md new file mode 100644 index 0000000..a38a1c3 --- /dev/null +++ b/docs/api/rhi/sampler/get-id.md @@ -0,0 +1,19 @@ +# RHISampler::GetID + +```cpp +virtual unsigned int GetID() = 0; +``` + +获取采样器 ID。 + +**返回:** 采样器唯一标识符 + +**示例:** + +```cpp +unsigned int id = sampler->GetID(); +``` + +## 相关文档 + +- [RHISampler 总览](sampler.md) - 返回类总览 diff --git a/docs/api/rhi/sampler/get-native-handle.md b/docs/api/rhi/sampler/get-native-handle.md new file mode 100644 index 0000000..5cf1eb0 --- /dev/null +++ b/docs/api/rhi/sampler/get-native-handle.md @@ -0,0 +1,15 @@ +# RHISampler::GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 + +**返回:** 原生采样器句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [RHISampler 总览](sampler.md) - 返回类总览 diff --git a/docs/api/rhi/sampler/methods.md b/docs/api/rhi/sampler/methods.md new file mode 100644 index 0000000..a4307b0 --- /dev/null +++ b/docs/api/rhi/sampler/methods.md @@ -0,0 +1,41 @@ +# RHISampler 方法 + +## Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +释放采样器资源。 + +## Bind + +```cpp +virtual void Bind(unsigned int unit) = 0; +``` + +绑定采样器到纹理单元。 + +## Unbind + +```cpp +virtual void Unbind(unsigned int unit) = 0; +``` + +解绑采样器。 + +## GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 + +## GetID + +```cpp +virtual unsigned int GetID() = 0; +``` + +获取采样器 ID。 diff --git a/docs/api/rhi/sampler/sampler.md b/docs/api/rhi/sampler/sampler.md new file mode 100644 index 0000000..6722404 --- /dev/null +++ b/docs/api/rhi/sampler/sampler.md @@ -0,0 +1,22 @@ +# RHISampler + +**命名空间**: `XCEngine::RHI` + +**类型**: `class` (abstract) + +**描述**: GPU 纹理采样器抽象接口,用于配置纹理过滤和寻址模式。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Shutdown`](shutdown.md) | 关闭并释放资源 | +| [`Bind`](../shader/bind.md) | 绑定采样器 | +| [`Unbind`](../shader/unbind.md) | 解绑采样器 | +| [`GetNativeHandle`](get-native-handle.md) | 获取原生句柄 | +| [`GetID`](get-id.md) | 获取采样器 ID | + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHITexture](../texture/texture.md) - 纹理资源 diff --git a/docs/api/rhi/sampler/shutdown.md b/docs/api/rhi/sampler/shutdown.md new file mode 100644 index 0000000..9fe1895 --- /dev/null +++ b/docs/api/rhi/sampler/shutdown.md @@ -0,0 +1,13 @@ +# RHISampler::Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +释放采样器资源。 + +**复杂度:** O(1) + +## 相关文档 + +- [RHISampler 总览](sampler.md) - 返回类总览 diff --git a/docs/api/rhi/shader/bind.md b/docs/api/rhi/shader/bind.md new file mode 100644 index 0000000..b546111 --- /dev/null +++ b/docs/api/rhi/shader/bind.md @@ -0,0 +1,20 @@ +# RHIShader::Bind + +```cpp +virtual void Bind() = 0; +``` + +绑定着色器到管线。 + +**复杂度:** O(1) + +**示例:** + +```cpp +vs->Bind(); +ps->Bind(); +``` + +## 相关文档 + +- [RHIShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/shader/compile-from-file.md b/docs/api/rhi/shader/compile-from-file.md new file mode 100644 index 0000000..92a28a5 --- /dev/null +++ b/docs/api/rhi/shader/compile-from-file.md @@ -0,0 +1,26 @@ +# RHIShader::CompileFromFile + +```cpp +virtual bool CompileFromFile(const wchar_t* filePath, const char* entryPoint, const char* target) = 0; +``` + +从文件编译着色器。 + +**参数:** +- `filePath` - 着色器源文件路径 +- `entryPoint` - 入口点函数名 +- `target` - 编译目标(如 `"vs_6_0"`, `"ps_6_0"`) + +**返回:** 成功返回 `true`,失败返回 `false` + +**复杂度:** O(n) - 取决于着色器代码复杂度 + +**示例:** + +```cpp +shader->CompileFromFile(L"shaders/vertex.hlsl", "main", "vs_6_0"); +``` + +## 相关文档 + +- [RHIShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/shader/compile.md b/docs/api/rhi/shader/compile.md new file mode 100644 index 0000000..b903239 --- /dev/null +++ b/docs/api/rhi/shader/compile.md @@ -0,0 +1,21 @@ +# RHIShader::Compile + +```cpp +virtual bool Compile(const void* sourceData, size_t sourceSize, const char* entryPoint, const char* target) = 0; +``` + +从内存编译着色器。 + +**参数:** +- `sourceData` - 着色器源代码指针 +- `sourceSize` - 源代码大小 +- `entryPoint` - 入口点函数名 +- `target` - 编译目标 + +**返回:** 成功返回 `true`,失败返回 `false` + +**复杂度:** O(n) + +## 相关文档 + +- [RHIShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/shader/get-native-handle.md b/docs/api/rhi/shader/get-native-handle.md new file mode 100644 index 0000000..d46e059 --- /dev/null +++ b/docs/api/rhi/shader/get-native-handle.md @@ -0,0 +1,15 @@ +# RHIShader::GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 + +**返回:** 原生着色器句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/shader/get-type.md b/docs/api/rhi/shader/get-type.md new file mode 100644 index 0000000..5b364da --- /dev/null +++ b/docs/api/rhi/shader/get-type.md @@ -0,0 +1,15 @@ +# RHIShader::GetType + +```cpp +virtual ShaderType GetType() const = 0; +``` + +获取着色器类型。 + +**返回:** 着色器类型枚举值 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/shader/is-valid.md b/docs/api/rhi/shader/is-valid.md new file mode 100644 index 0000000..56597ea --- /dev/null +++ b/docs/api/rhi/shader/is-valid.md @@ -0,0 +1,15 @@ +# RHIShader::IsValid + +```cpp +virtual bool IsValid() const = 0; +``` + +检查着色器是否有效(已成功编译)。 + +**返回:** 有效返回 `true`,无效返回 `false` + +**复杂度:** O(1) + +## 相关文档 + +- [RHIShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/shader/set-float.md b/docs/api/rhi/shader/set-float.md new file mode 100644 index 0000000..89f6ad1 --- /dev/null +++ b/docs/api/rhi/shader/set-float.md @@ -0,0 +1,17 @@ +# RHIShader::SetFloat + +```cpp +virtual void SetFloat(const char* name, float value) = 0; +``` + +设置浮点 uniform。 + +**参数:** +- `name` - uniform 变量名 +- `value` - 浮点值 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/shader/set-int.md b/docs/api/rhi/shader/set-int.md new file mode 100644 index 0000000..1bddd31 --- /dev/null +++ b/docs/api/rhi/shader/set-int.md @@ -0,0 +1,17 @@ +# RHIShader::SetInt + +```cpp +virtual void SetInt(const char* name, int value) = 0; +``` + +设置整数 uniform。 + +**参数:** +- `name` - uniform 变量名 +- `value` - 整数值 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/shader/set-mat4.md b/docs/api/rhi/shader/set-mat4.md new file mode 100644 index 0000000..b739e3f --- /dev/null +++ b/docs/api/rhi/shader/set-mat4.md @@ -0,0 +1,17 @@ +# RHIShader::SetMat4 + +```cpp +virtual void SetMat4(const char* name, const float* value) = 0; +``` + +设置 4x4 矩阵 uniform。 + +**参数:** +- `name` - uniform 变量名 +- `value` - 矩阵数据指针(16 个 float) + +**复杂度:** O(1) + +## 相关文档 + +- [RHIShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/shader/set-vec3.md b/docs/api/rhi/shader/set-vec3.md new file mode 100644 index 0000000..3ef8665 --- /dev/null +++ b/docs/api/rhi/shader/set-vec3.md @@ -0,0 +1,17 @@ +# RHIShader::SetVec3 + +```cpp +virtual void SetVec3(const char* name, float x, float y, float z) = 0; +``` + +设置三维向量 uniform。 + +**参数:** +- `name` - uniform 变量名 +- `x, y, z` - 向量分量 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/shader/set-vec4.md b/docs/api/rhi/shader/set-vec4.md new file mode 100644 index 0000000..b3e456f --- /dev/null +++ b/docs/api/rhi/shader/set-vec4.md @@ -0,0 +1,17 @@ +# RHIShader::SetVec4 + +```cpp +virtual void SetVec4(const char* name, float x, float y, float z, float w) = 0; +``` + +设置四维向量 uniform。 + +**参数:** +- `name` - uniform 变量名 +- `x, y, z, w` - 向量分量 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/shader/shader.md b/docs/api/rhi/shader/shader.md new file mode 100644 index 0000000..8993247 --- /dev/null +++ b/docs/api/rhi/shader/shader.md @@ -0,0 +1,55 @@ +# RHIShader + +**命名空间**: `XCEngine::RHI` + +**类型**: `class` (abstract) + +**描述**: GPU 着色器资源抽象接口,用于管理着色器代码的编译和绑定。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`CompileFromFile`](compile-from-file.md) | 从文件编译着色器 | +| [`Compile`](compile.md) | 从源码编译着色器 | +| [`GetType`](get-type.md) | 获取着色器类型 | +| [`IsValid`](is-valid.md) | 检查着色器是否有效 | +| [`Bind`](bind.md) | 绑定着色器 | +| [`Unbind`](unbind.md) | 解绑着色器 | +| [`SetInt`](set-int.md) | 设置整数 uniform | +| [`SetFloat`](set-float.md) | 设置浮点数 uniform | +| [`SetVec3`](set-vec3.md) | 设置 vec3 uniform | +| [`SetVec4`](set-vec4.md) | 设置 vec4 uniform | +| [`SetMat4`](set-mat4.md) | 设置 mat4 uniform | +| [`Shutdown`](shutdown.md) | 关闭并释放资源 | +| [`GetNativeHandle`](get-native-handle.md) | 获取原生句柄 | + +## 着色器类型 (ShaderType) + +| 枚举值 | 描述 | +|--------|------| +| `ShaderType::Vertex` | 顶点着色器 | +| `ShaderType::Fragment` | 片元着色器 | +| `ShaderType::Geometry` | 几何着色器 | +| `ShaderType::Compute` | 计算着色器 | +| `ShaderType::TessControl` | 曲面细分控制着色器 | +| `ShaderType::TessEvaluation` | 曲面细分评估着色器 | +| `ShaderType::Hull` | Hull 着色器 (D3D12) | +| `ShaderType::Domain` | Domain 着色器 (D3D12) | +| `ShaderType::Amplification` | 放大着色器 (Mesh Shader) | +| `ShaderType::Mesh` | Mesh 着色器 | +| `ShaderType::Library` | 着色器库 | + +## 使用示例 + +```cpp +RHIShader* vs = device->CompileShader({}); +vs->CompileFromFile(L"shaders/vertex.hlsl", "main", "vs_6_0"); +vs->SetMat4("modelMatrix", modelMatrix); +vs->Bind(); +``` + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHIDevice](../device/device.md) - 创建设备 diff --git a/docs/api/rhi/shader/shutdown.md b/docs/api/rhi/shader/shutdown.md new file mode 100644 index 0000000..9972cef --- /dev/null +++ b/docs/api/rhi/shader/shutdown.md @@ -0,0 +1,13 @@ +# RHIShader::Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +释放着色器资源。 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/shader/unbind.md b/docs/api/rhi/shader/unbind.md new file mode 100644 index 0000000..53aedf6 --- /dev/null +++ b/docs/api/rhi/shader/unbind.md @@ -0,0 +1,13 @@ +# RHIShader::Unbind + +```cpp +virtual void Unbind() = 0; +``` + +解绑着色器。 + +**复杂度:** O(1) + +## 相关文档 + +- [RHIShader 总览](shader.md) - 返回类总览 diff --git a/docs/api/rhi/swap-chain/get-current-back-buffer-index.md b/docs/api/rhi/swap-chain/get-current-back-buffer-index.md new file mode 100644 index 0000000..18666df --- /dev/null +++ b/docs/api/rhi/swap-chain/get-current-back-buffer-index.md @@ -0,0 +1,19 @@ +# RHISwapChain::GetCurrentBackBufferIndex + +```cpp +virtual uint32_t GetCurrentBackBufferIndex() const = 0; +``` + +获取当前后台缓冲区索引。 + +**返回:** 当前后台缓冲区索引 + +**示例:** + +```cpp +uint32_t index = swapChain->GetCurrentBackBufferIndex(); +``` + +## 相关文档 + +- [RHISwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/swap-chain/get-current-back-buffer.md b/docs/api/rhi/swap-chain/get-current-back-buffer.md new file mode 100644 index 0000000..b068535 --- /dev/null +++ b/docs/api/rhi/swap-chain/get-current-back-buffer.md @@ -0,0 +1,19 @@ +# RHISwapChain::GetCurrentBackBuffer + +```cpp +virtual RHITexture* GetCurrentBackBuffer() = 0; +``` + +获取当前后台缓冲区纹理。 + +**返回:** 当前后台缓冲区纹理指针 + +**示例:** + +```cpp +RHITexture* backBuffer = swapChain->GetCurrentBackBuffer(); +``` + +## 相关文档 + +- [RHISwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/swap-chain/get-native-handle.md b/docs/api/rhi/swap-chain/get-native-handle.md new file mode 100644 index 0000000..eeacab3 --- /dev/null +++ b/docs/api/rhi/swap-chain/get-native-handle.md @@ -0,0 +1,15 @@ +# RHISwapChain::GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 + +**返回:** 原生交换链句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [RHISwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/swap-chain/is-fullscreen.md b/docs/api/rhi/swap-chain/is-fullscreen.md new file mode 100644 index 0000000..f7ef1b0 --- /dev/null +++ b/docs/api/rhi/swap-chain/is-fullscreen.md @@ -0,0 +1,21 @@ +# RHISwapChain::IsFullscreen + +```cpp +virtual bool IsFullscreen() const = 0; +``` + +检查是否处于全屏模式。 + +**返回:** 如果全屏返回 true + +**示例:** + +```cpp +if (swapChain->IsFullscreen()) { + // 全屏模式 +} +``` + +## 相关文档 + +- [RHISwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/swap-chain/methods.md b/docs/api/rhi/swap-chain/methods.md new file mode 100644 index 0000000..5f2ac89 --- /dev/null +++ b/docs/api/rhi/swap-chain/methods.md @@ -0,0 +1,89 @@ +# RHISwapChain 方法 + +## Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +关闭交换链。 + +## GetCurrentBackBufferIndex + +```cpp +virtual uint32_t GetCurrentBackBufferIndex() const = 0; +``` + +获取当前后台缓冲索引。 + +## GetCurrentBackBuffer + +```cpp +virtual RHITexture* GetCurrentBackBuffer() = 0; +``` + +获取当前后台缓冲纹理。 + +## Present + +```cpp +virtual void Present(uint32_t syncInterval = 1, uint32_t flags = 0) = 0; +``` + +呈现渲染结果。 + +## Resize + +```cpp +virtual void Resize(uint32_t width, uint32_t height) = 0; +``` + +调整交换链大小。 + +## SetFullscreen + +```cpp +virtual void SetFullscreen(bool fullscreen) = 0; +``` + +设置全屏模式。 + +## IsFullscreen + +```cpp +virtual bool IsFullscreen() const = 0; +``` + +检查是否全屏。 + +## ShouldClose + +```cpp +virtual bool ShouldClose() const = 0; +``` + +检查是否应该关闭。 + +## SetShouldClose + +```cpp +virtual void SetShouldClose(bool shouldClose) = 0; +``` + +设置关闭标志。 + +## PollEvents + +```cpp +virtual void PollEvents() = 0; +``` + +处理窗口事件。 + +## GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 diff --git a/docs/api/rhi/swap-chain/poll-events.md b/docs/api/rhi/swap-chain/poll-events.md new file mode 100644 index 0000000..c49d872 --- /dev/null +++ b/docs/api/rhi/swap-chain/poll-events.md @@ -0,0 +1,17 @@ +# RHISwapChain::PollEvents + +```cpp +virtual void PollEvents() = 0; +``` + +处理窗口事件。 + +**示例:** + +```cpp +swapChain->PollEvents(); +``` + +## 相关文档 + +- [RHISwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/swap-chain/present.md b/docs/api/rhi/swap-chain/present.md new file mode 100644 index 0000000..ca10e72 --- /dev/null +++ b/docs/api/rhi/swap-chain/present.md @@ -0,0 +1,21 @@ +# RHISwapChain::Present + +```cpp +virtual void Present(uint32_t syncInterval = 1, uint32_t flags = 0) = 0; +``` + +呈现后台缓冲区。 + +**参数:** +- `syncInterval` - 垂直同步间隔(0=立即,1+=等待) +- `flags` - 呈现标志 + +**示例:** + +```cpp +swapChain->Present(1); // 垂直同步呈现 +``` + +## 相关文档 + +- [RHISwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/swap-chain/resize.md b/docs/api/rhi/swap-chain/resize.md new file mode 100644 index 0000000..d18a098 --- /dev/null +++ b/docs/api/rhi/swap-chain/resize.md @@ -0,0 +1,27 @@ +# RHISwapChain::Resize + +```cpp +virtual void Resize(uint32_t width, uint32_t height) = 0; +``` + +调整交换链大小。 + +**参数:** +- `width` - 新的宽度 +- `height` - 新的高度 + +**复杂度:** O(n) - 取决于缓冲区数量 + +**注意:** +- 调整大小会导致所有后台缓冲区重建 +- 应在渲染循环外调用 + +**示例:** + +```cpp +swapChain->Resize(1920, 1080); +``` + +## 相关文档 + +- [RHISwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/swap-chain/set-fullscreen.md b/docs/api/rhi/swap-chain/set-fullscreen.md new file mode 100644 index 0000000..bdc99ac --- /dev/null +++ b/docs/api/rhi/swap-chain/set-fullscreen.md @@ -0,0 +1,20 @@ +# RHISwapChain::SetFullscreen + +```cpp +virtual void SetFullscreen(bool fullscreen) = 0; +``` + +设置全屏模式。 + +**参数:** +- `fullscreen` - 是否全屏 + +**示例:** + +```cpp +swapChain->SetFullscreen(true); +``` + +## 相关文档 + +- [RHISwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/swap-chain/set-should-close.md b/docs/api/rhi/swap-chain/set-should-close.md new file mode 100644 index 0000000..f16d4dc --- /dev/null +++ b/docs/api/rhi/swap-chain/set-should-close.md @@ -0,0 +1,20 @@ +# RHISwapChain::SetShouldClose + +```cpp +virtual void SetShouldClose(bool shouldClose) = 0; +``` + +设置交换链关闭标志。 + +**参数:** +- `shouldClose` - 是否应该关闭 + +**示例:** + +```cpp +swapChain->SetShouldClose(true); +``` + +## 相关文档 + +- [RHISwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/swap-chain/should-close.md b/docs/api/rhi/swap-chain/should-close.md new file mode 100644 index 0000000..7d7eed3 --- /dev/null +++ b/docs/api/rhi/swap-chain/should-close.md @@ -0,0 +1,21 @@ +# RHISwapChain::ShouldClose + +```cpp +virtual bool ShouldClose() const = 0; +``` + +检查交换链是否应该关闭。 + +**返回:** 如果应该关闭返回 true + +**示例:** + +```cpp +while (!swapChain->ShouldClose()) { + // 渲染循环 +} +``` + +## 相关文档 + +- [RHISwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/swap-chain/shutdown.md b/docs/api/rhi/swap-chain/shutdown.md new file mode 100644 index 0000000..07f8d25 --- /dev/null +++ b/docs/api/rhi/swap-chain/shutdown.md @@ -0,0 +1,13 @@ +# RHISwapChain::Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +关闭交换链,释放所有相关资源。 + +**复杂度:** O(n) - 取决于管理的缓冲区数量 + +## 相关文档 + +- [RHISwapChain 总览](swap-chain.md) - 返回类总览 diff --git a/docs/api/rhi/swap-chain/swap-chain.md b/docs/api/rhi/swap-chain/swap-chain.md new file mode 100644 index 0000000..9deaa4d --- /dev/null +++ b/docs/api/rhi/swap-chain/swap-chain.md @@ -0,0 +1,43 @@ +# RHISwapChain + +**命名空间**: `XCEngine::RHI` + +**类型**: `class` (abstract) + +**描述**: GPU 交换链抽象接口,用于管理窗口渲染和帧缓冲区切换。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Shutdown`](shutdown.md) | 关闭并释放资源 | +| [`GetCurrentBackBufferIndex`](get-current-back-buffer-index.md) | 获取当前后台缓冲区索引 | +| [`GetCurrentBackBuffer`](get-current-back-buffer.md) | 获取当前后台缓冲区 | +| [`Present`](present.md) | 呈现画面 | +| [`Resize`](resize.md) | 调整交换链大小 | +| [`SetFullscreen`](set-fullscreen.md) | 设置全屏模式 | +| [`IsFullscreen`](is-fullscreen.md) | 检查是否全屏 | +| [`ShouldClose`](should-close.md) | 检查是否应关闭 | +| [`SetShouldClose`](set-should-close.md) | 设置关闭标志 | +| [`PollEvents`](poll-events.md) | 处理窗口事件 | +| [`GetNativeHandle`](get-native-handle.md) | 获取原生句柄 | + +## 使用示例 + +```cpp +while (!swapChain->ShouldClose()) { + swapChain->PollEvents(); + RHITexture* backBuffer = swapChain->GetCurrentBackBuffer(); + commandList->Reset(); + commandList->SetRenderTargets(1, &backBuffer, nullptr); + commandList->ClearRenderTarget(backBuffer, clearColor); + commandList->Close(); + commandQueue->ExecuteCommandLists(1, (void**)&commandList); + swapChain->Present(1, 0); +} +``` + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHITexture](../texture/texture.md) - 纹理资源 diff --git a/docs/api/rhi/texture/get-depth.md b/docs/api/rhi/texture/get-depth.md new file mode 100644 index 0000000..fdaf4dd --- /dev/null +++ b/docs/api/rhi/texture/get-depth.md @@ -0,0 +1,15 @@ +# RHITexture::GetDepth + +```cpp +virtual uint32_t GetDepth() const = 0; +``` + +获取纹理深度(3D 纹理)。 + +**返回:** 纹理深度 + +**复杂度:** O(1) + +## 相关文档 + +- [RHITexture 总览](texture.md) - 返回类总览 diff --git a/docs/api/rhi/texture/get-format.md b/docs/api/rhi/texture/get-format.md new file mode 100644 index 0000000..50fd3c9 --- /dev/null +++ b/docs/api/rhi/texture/get-format.md @@ -0,0 +1,15 @@ +# RHITexture::GetFormat + +```cpp +virtual Format GetFormat() const = 0; +``` + +获取纹理格式。 + +**返回:** 纹理格式枚举值 + +**复杂度:** O(1) + +## 相关文档 + +- [RHITexture 总览](texture.md) - 返回类总览 diff --git a/docs/api/rhi/texture/get-height.md b/docs/api/rhi/texture/get-height.md new file mode 100644 index 0000000..fe5675e --- /dev/null +++ b/docs/api/rhi/texture/get-height.md @@ -0,0 +1,15 @@ +# RHITexture::GetHeight + +```cpp +virtual uint32_t GetHeight() const = 0; +``` + +获取纹理高度(像素)。 + +**返回:** 纹理高度 + +**复杂度:** O(1) + +## 相关文档 + +- [RHITexture 总览](texture.md) - 返回类总览 diff --git a/docs/api/rhi/texture/get-mip-levels.md b/docs/api/rhi/texture/get-mip-levels.md new file mode 100644 index 0000000..3c0e74c --- /dev/null +++ b/docs/api/rhi/texture/get-mip-levels.md @@ -0,0 +1,15 @@ +# RHITexture::GetMipLevels + +```cpp +virtual uint32_t GetMipLevels() const = 0; +``` + +获取 Mipmap 级别数。 + +**返回:** Mipmap 级别数 + +**复杂度:** O(1) + +## 相关文档 + +- [RHITexture 总览](texture.md) - 返回类总览 diff --git a/docs/api/rhi/texture/get-name.md b/docs/api/rhi/texture/get-name.md new file mode 100644 index 0000000..a2ede79 --- /dev/null +++ b/docs/api/rhi/texture/get-name.md @@ -0,0 +1,20 @@ +# RHITexture::GetName / SetName + +```cpp +virtual const std::string& GetName() const = 0; +virtual void SetName(const std::string& name) = 0; +``` + +获取或设置纹理名称(用于调试)。 + +**复杂度:** O(1) + +**示例:** + +```cpp +texture->SetName("DiffuseMap_Main"); +``` + +## 相关文档 + +- [RHITexture 总览](texture.md) - 返回类总览 diff --git a/docs/api/rhi/texture/get-native-handle.md b/docs/api/rhi/texture/get-native-handle.md new file mode 100644 index 0000000..eac0e54 --- /dev/null +++ b/docs/api/rhi/texture/get-native-handle.md @@ -0,0 +1,15 @@ +# RHITexture::GetNativeHandle + +```cpp +virtual void* GetNativeHandle() = 0; +``` + +获取原生 API 句柄。 + +**返回:** 原生纹理句柄 + +**复杂度:** O(1) + +## 相关文档 + +- [RHITexture 总览](texture.md) - 返回类总览 diff --git a/docs/api/rhi/texture/get-state.md b/docs/api/rhi/texture/get-state.md new file mode 100644 index 0000000..2b907ad --- /dev/null +++ b/docs/api/rhi/texture/get-state.md @@ -0,0 +1,15 @@ +# RHITexture::GetState + +```cpp +virtual ResourceStates GetState() const = 0; +``` + +获取当前资源状态。 + +**返回:** 资源状态枚举值 + +**复杂度:** O(1) + +## 相关文档 + +- [RHITexture 总览](texture.md) - 返回类总览 diff --git a/docs/api/rhi/texture/get-texture-type.md b/docs/api/rhi/texture/get-texture-type.md new file mode 100644 index 0000000..3081d47 --- /dev/null +++ b/docs/api/rhi/texture/get-texture-type.md @@ -0,0 +1,15 @@ +# RHITexture::GetTextureType + +```cpp +virtual TextureType GetTextureType() const = 0; +``` + +获取纹理类型。 + +**返回:** 纹理类型枚举值 + +**复杂度:** O(1) + +## 相关文档 + +- [RHITexture 总览](texture.md) - 返回类总览 diff --git a/docs/api/rhi/texture/get-width.md b/docs/api/rhi/texture/get-width.md new file mode 100644 index 0000000..9b33962 --- /dev/null +++ b/docs/api/rhi/texture/get-width.md @@ -0,0 +1,15 @@ +# RHITexture::GetWidth + +```cpp +virtual uint32_t GetWidth() const = 0; +``` + +获取纹理宽度(像素)。 + +**返回:** 纹理宽度 + +**复杂度:** O(1) + +## 相关文档 + +- [RHITexture 总览](texture.md) - 返回类总览 diff --git a/docs/api/rhi/texture/set-name.md b/docs/api/rhi/texture/set-name.md new file mode 100644 index 0000000..5300884 --- /dev/null +++ b/docs/api/rhi/texture/set-name.md @@ -0,0 +1,22 @@ +# RHITexture::SetName + +```cpp +virtual void SetName(const std::string& name) = 0; +``` + +设置纹理名称(用于调试)。 + +**参数:** +- `name` - 新名称 + +**复杂度:** O(1) + +**示例:** + +```cpp +texture->SetName("DiffuseMap"); +``` + +## 相关文档 + +- [RHITexture 总览](texture.md) - 返回类总览 diff --git a/docs/api/rhi/texture/set-state.md b/docs/api/rhi/texture/set-state.md new file mode 100644 index 0000000..5956f72 --- /dev/null +++ b/docs/api/rhi/texture/set-state.md @@ -0,0 +1,22 @@ +# RHITexture::SetState + +```cpp +virtual void SetState(ResourceStates state) = 0; +``` + +设置资源状态。 + +**参数:** +- `state` - 新的资源状态 + +**复杂度:** O(1) + +**示例:** + +```cpp +texture->SetState(ResourceStates::PixelShaderResource); +``` + +## 相关文档 + +- [RHITexture 总览](texture.md) - 返回类总览 diff --git a/docs/api/rhi/texture/shutdown.md b/docs/api/rhi/texture/shutdown.md new file mode 100644 index 0000000..9ccf4be --- /dev/null +++ b/docs/api/rhi/texture/shutdown.md @@ -0,0 +1,13 @@ +# RHITexture::Shutdown + +```cpp +virtual void Shutdown() = 0; +``` + +释放纹理资源。 + +**复杂度:** O(1) + +## 相关文档 + +- [RHITexture 总览](texture.md) - 返回类总览 diff --git a/docs/api/rhi/texture/texture.md b/docs/api/rhi/texture/texture.md new file mode 100644 index 0000000..2b27912 --- /dev/null +++ b/docs/api/rhi/texture/texture.md @@ -0,0 +1,80 @@ +# RHITexture + +**命名空间**: `XCEngine::RHI` + +**类型**: `class` (abstract) + +**描述**: GPU 纹理资源抽象接口,用于管理 1D、2D、3D 纹理和立方体贴图等 GPU 资源。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`GetWidth`](get-width.md) | 获取纹理宽度 | +| [`GetHeight`](get-height.md) | 获取纹理高度 | +| [`GetDepth`](get-depth.md) | 获取纹理深度 | +| [`GetMipLevels`](get-mip-levels.md) | 获取 Mip 级别数量 | +| [`GetFormat`](get-format.md) | 获取纹理格式 | +| [`GetTextureType`](get-texture-type.md) | 获取纹理类型 | +| [`GetState`](get-state.md) | 获取资源状态 | +| [`SetState`](set-state.md) | 设置资源状态 | +| [`Shutdown`](shutdown.md) | 关闭并释放资源 | +| [`GetNativeHandle`](get-native-handle.md) | 获取原生句柄 | +| [`GetName`](get-name.md) | 获取资源名称 | +| [`SetName`](set-name.md) | 设置资源名称 | + +## 纹理类型 (TextureType) + +| 枚举值 | 描述 | +|--------|------| +| `TextureType::Texture1D` | 1D 纹理 | +| `TextureType::Texture2D` | 2D 纹理 | +| `TextureType::Texture2DArray` | 2D 纹理数组 | +| `TextureType::Texture3D` | 3D 纹理(体积纹理) | +| `TextureType::TextureCube` | 立方体贴图 | +| `TextureType::TextureCubeArray` | 立方体贴图数组 | + +## 纹理格式 (Format) + +| 格式 | 描述 | +|------|------| +| `Format::Unknown` | 未知格式 | +| `Format::R8_UNorm` | 单通道 8 位归一化 | +| `Format::R8G8_UNorm` | 双通道 8 位归一化 | +| `Format::R8G8B8A8_UNorm` | 四通道 8 位归一化 | +| `Format::R16G16B16A16_Float` | 四通道 16 位浮点 | +| `Format::R32G32B32A32_Float` | 四通道 32 位浮点 | +| `Format::R16_Float` | 单通道 16 位浮点 | +| `Format::R32_Float` | 单通道 32 位浮点 | +| `Format::D16_UNorm` | 16 位深度 | +| `Format::D24_UNorm_S8_UInt` | 24 位深度 + 8 位模板 | +| `Format::D32_Float` | 32 位深度 | +| `Format::BC1_UNorm` | BC1 压缩 (DXT1) | +| `Format::BC2_UNorm` | BC2 压缩 (DXT2/3) | +| `Format::BC3_UNorm` | BC3 压缩 (DXT4/5) | +| `Format::BC4_UNorm` | BC4 压缩 | +| `Format::BC5_UNorm` | BC5 压缩 | +| `Format::BC6H_UF16` | BC6H 压缩 (UF16) | +| `Format::BC7_UNorm` | BC7 高质量压缩 | +| `Format::R32G32B32A32_UInt` | 四通道 32 位无符号整数 | +| `Format::R32_UInt` | 单通道 32 位无符号整数 | + +## 使用示例 + +```cpp +TextureDesc desc; +desc.width = 1024; +desc.height = 1024; +desc.format = (uint32_t)Format::R8G8B8A8_UNorm; +desc.textureType = (uint32_t)TextureType::Texture2D; + +RHITexture* texture = device->CreateTexture(desc); +texture->SetState(ResourceStates::PixelShaderResource); +texture->Shutdown(); +``` + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHIDevice](../device/device.md) - 创建设备 +- [RHIBuffer](../buffer/buffer.md) - 缓冲区资源 diff --git a/docs/api/rhi/types/types.md b/docs/api/rhi/types/types.md new file mode 100644 index 0000000..67e72f1 --- /dev/null +++ b/docs/api/rhi/types/types.md @@ -0,0 +1,81 @@ +# RHITypes + +**命名空间**: `XCEngine::RHI` + +**类型**: `structs` + +**描述**: RHI 模块中使用的所有结构体类型汇总。 + +## 概述 + +本模块汇总了 RHI 模块中定义的所有结构体类型。这些结构体用于配置各种资源的创建和渲染状态。 + +## 主要结构体 + +### 视口和矩形 + +| 结构体 | 描述 | +|--------|------| +| `Viewport` | 视口结构体 | +| `Rect` | 裁剪矩形结构体 | +| `Color` | 颜色结构体 | +| `ClearValue` | 清除值结构体 | + +### 着色器 + +| 结构体 | 描述 | +|--------|------| +| `ShaderCompileMacro` | 着色器编译宏定义 | +| `ShaderCompileDesc` | 着色器编译描述 | +| `InputElementDesc` | 输入布局元素描述 | +| `InputLayoutDesc` | 输入布局描述 | + +### 资源和描述符 + +| 结构体 | 描述 | +|--------|------| +| `TextureDesc` | 纹理描述 | +| `BufferDesc` | 缓冲区描述 | +| `RenderTargetDesc` | 渲染目标描述 | +| `DepthStencilDesc` | 深度模板描述 | +| `DescriptorHeapDesc` | 描述符堆描述 | +| `RenderTargetViewDesc` | 渲染目标视图描述 | +| `DepthStencilViewDesc` | 深度模板视图描述 | +| `ShaderResourceViewDesc` | 着色器资源视图描述 | +| `ConstantBufferViewDesc` | 常量缓冲视图描述 | +| `UnorderedAccessViewDesc` | 无序访问视图描述 | + +### 命令 + +| 结构体 | 描述 | +|--------|------| +| `CommandQueueDesc` | 命令队列描述 | +| `CommandListDesc` | 命令列表描述 | +| `CommandAllocatorDesc` | 命令分配器描述 | +| `FenceDesc` | 栅栏描述 | +| `QueryHeapDesc` | 查询堆描述 | +| `SamplerDesc` | 采样器描述 | +| `SwapChainDesc` | 交换链描述 | + +### 设备 + +| 结构体 | 描述 | +|--------|------| +| `RHIDeviceDesc` | 设备描述 | +| `RHIDeviceInfo` | 设备信息 | +| `RHIRenderPassDesc` | 渲染通道描述 | +| `RHIPipelineLayoutDesc` | 管线布局描述 | + +### 句柄 + +| 结构体 | 描述 | +|--------|------| +| `DescriptorHandle` | 描述符句柄 | +| `GPUDescriptorHandle` | GPU 描述符句柄 | +| `CPUDescriptorHandle` | CPU 描述符句柄 | +| `SubresourceRange` | 子资源范围 | + +## 相关文档 + +- [../rhi/rhi.md](../rhi.md) - RHI 模块总览 +- [RHIEnums](../enums/enums.md) - 枚举类型汇总 diff --git a/docs/api/threading/lambdatask/constructor.md b/docs/api/threading/lambdatask/constructor.md new file mode 100644 index 0000000..81d5642 --- /dev/null +++ b/docs/api/threading/lambdatask/constructor.md @@ -0,0 +1,41 @@ +# LambdaTask::LambdaTask + +```cpp +explicit LambdaTask(Func&& func, TaskPriority priority = TaskPriority::Normal) +``` + +构造 Lambda 任务对象,将可调用对象包装为 ITask。 + +**模板参数:** +- `Func` - 可调用对象类型 + +**参数:** +- `func` - 要封装的可调用对象(lambda、函数指针、std::function 等) +- `priority` - 任务优先级,默认值为 TaskPriority::Normal + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +// 使用 std::function lambda +auto task = std::make_unique>>( + []() { printf("Task executed\n"); }, + TaskPriority::High +); +TaskSystem::Get().Submit(std::move(task)); + +// 配合 TaskSystem::Submit 的重载直接使用 +TaskSystem::Get().Submit( + std::make_unique>>( + []() { ProcessData(); }, + TaskPriority::Critical + ) +); +``` + +## 相关文档 + +- [LambdaTask 总览](lambdatask.md) - 返回类总览 diff --git a/docs/api/threading/lambdatask/lambdatask.md b/docs/api/threading/lambdatask/lambdatask.md new file mode 100644 index 0000000..15c6ea2 --- /dev/null +++ b/docs/api/threading/lambdatask/lambdatask.md @@ -0,0 +1,57 @@ +# LambdaTask + +**命名空间**: `XCEngine::Threading` + +**类型**: `class` (template) + +**头文件**: `XCEngine/Threading/LambdaTask.h` + +**描述**: Lambda 任务封装模板类,允许使用 lambda 表达式创建任务,无需继承 ITask。 + +## 概述 + +`LambdaTask` 是一个模板封装类,将任意可调用对象(lambda、函数指针、std::function)包装为 `ITask`。这大大简化了简短任务的创建。 + +## 模板参数 + +| 参数 | 描述 | +|------|------| +| `Func` | 可调用对象类型 | + +## 构造方法 + +| 方法 | 描述 | +|------|------| +| [`LambdaTask`](constructor.md) | 构造 Lambda 任务 | + +## 继承方法 + +| 方法 | 描述 | +|------|------| +| `Execute()` | 执行封装的可调用对象(继承自 ITask,可重写) | + +## 使用示例 + +```cpp +// 使用 lambda 创建任务 +TaskSystem::Get().Submit( + std::make_unique>>( + []() { + printf("Hello from task!\n"); + }, + TaskPriority::Normal + ) +); + +// 或者直接使用 Submit 的便捷重载 +TaskSystem::Get().Submit([]() { + printf("Direct lambda task!\n"); +}); +``` + +## 相关文档 + +- [ITask](../task/task.md) - 任务基类 +- [TaskGroup](../task-group/task-group.md) - 任务组 +- [TaskSystem](../task-system/task-system.md) - 任务系统 +- [../threading/threading.md](../threading.md) - 模块总览 diff --git a/docs/api/threading/mutex/lock.md b/docs/api/threading/mutex/lock.md new file mode 100644 index 0000000..7fc8e74 --- /dev/null +++ b/docs/api/threading/mutex/lock.md @@ -0,0 +1,34 @@ +# Mutex::Lock + +```cpp +void Lock() +``` + +获取互斥锁。如果锁已被其他线程持有,则阻塞当前线程直到锁可用。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** 平均 O(1),最坏情况 O(n),n 为竞争线程数 + +**注意:** +- 同一线程不可重复 Lock 同一个 Mutex(会导致死锁)。 +- 建议使用 RAII 封装(如 std::lock_guard)自动管理锁的释放。 + +**示例:** + +```cpp +Threading::Mutex mtx; +int counter = 0; + +void Increment() { + mtx.Lock(); + ++counter; + mtx.Unlock(); +} +``` + +## 相关文档 + +- [Mutex 总览](mutex.md) - 返回类总览 diff --git a/docs/api/threading/mutex/mutex.md b/docs/api/threading/mutex/mutex.md new file mode 100644 index 0000000..3fe1e9e --- /dev/null +++ b/docs/api/threading/mutex/mutex.md @@ -0,0 +1,54 @@ +# Mutex + +**命名空间**: `XCEngine::Threading` + +**类型**: `class` + +**头文件**: `XCEngine/Threading/Mutex.h` + +**描述**: 互斥锁封装类,基于 `std::mutex` 实现,提供线程安全的互斥访问。 + +## 概述 + +`Mutex` 是对 `std::mutex` 的简单封装,提供了标准的 Lock/Unlock/TryLock 接口。它是 XCEngine 中最基础的同步原语,适用于保护共享数据的访问。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Lock`](lock.md) | 获取锁(阻塞) | +| [`Unlock`](unlock.md) | 释放锁 | +| [`TryLock`](trylock.md) | 尝试获取锁(非阻塞,成功返回 true) | + +## STL 兼容方法 + +支持 `lock()`, `unlock()`, `try_lock()` 以兼容 STL 的 lockable 概念。**注意**:这些方法为 `const` 成员函数。 + +## 使用示例 + +```cpp +Threading::Mutex mtx; +int sharedData = 0; + +// 线程安全地修改共享数据 +void SafeIncrement() { + mtx.Lock(); + ++sharedData; + mtx.Unlock(); +} + +// 或使用 TryLock +void SafeTryIncrement() { + if (mtx.TryLock()) { + ++sharedData; + mtx.Unlock(); + } +} +``` + +## 相关文档 + +- [SpinLock](../spinlock/spinlock.md) - 自旋锁 +- [ReadWriteLock](../readwritelock/readwritelock.md) - 读写锁 +- [TaskSystem](../task-system/task-system.md) - 任务系统 +- [../threading/threading.md](../threading.md) - 模块总览 diff --git a/docs/api/threading/mutex/trylock.md b/docs/api/threading/mutex/trylock.md new file mode 100644 index 0000000..8ae80c6 --- /dev/null +++ b/docs/api/threading/mutex/trylock.md @@ -0,0 +1,36 @@ +# Mutex::TryLock + +```cpp +bool TryLock() +``` + +尝试获取互斥锁(非阻塞)。如果锁可用则立即获取并返回 true,否则立即返回 false 而不阻塞。 + +**参数:** 无 + +**返回:** `bool` - 获取成功返回 true,锁不可用返回 false + +**复杂度:** O(1) + +**使用场景:** 适用于需要尝试获取锁但不希望阻塞的场景,如实现无锁算法或避免死锁。 + +**示例:** + +```cpp +Threading::Mutex mtx; +volatile bool updated = false; + +void TryUpdate() { + if (mtx.TryLock()) { + updated = true; + mtx.Unlock(); + printf("Update succeeded\n"); + } else { + printf("Update skipped (lock held)\n"); + } +} +``` + +## 相关文档 + +- [Mutex 总览](mutex.md) - 返回类总览 diff --git a/docs/api/threading/mutex/unlock.md b/docs/api/threading/mutex/unlock.md new file mode 100644 index 0000000..b8c7c6a --- /dev/null +++ b/docs/api/threading/mutex/unlock.md @@ -0,0 +1,32 @@ +# Mutex::Unlock + +```cpp +void Unlock() +``` + +释放互斥锁,允许其他等待中的线程获取该锁。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**注意:** 必须在持有锁的线程中调用 Unlock。解锁一个未持有的锁将导致未定义行为。 + +**示例:** + +```cpp +Threading::Mutex mtx; +std::vector data; + +void SafePush(int value) { + mtx.Lock(); + data.push_back(value); + mtx.Unlock(); +} +``` + +## 相关文档 + +- [Mutex 总览](mutex.md) - 返回类总览 diff --git a/docs/api/threading/readwritelock/readlock.md b/docs/api/threading/readwritelock/readlock.md new file mode 100644 index 0000000..57a71f5 --- /dev/null +++ b/docs/api/threading/readwritelock/readlock.md @@ -0,0 +1,36 @@ +# ReadWriteLock::ReadLock + +```cpp +void ReadLock() +``` + +获取读锁。如果有写者持有锁或正在等待写锁,当前线程将阻塞,直到所有写者完成。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** 平均 O(1) + +**注意:** +- 多个读者可以同时持有读锁。 +- 写锁具有优先权——正在等待的写者会阻塞新的读者,防止写者饥饿。 +- 读锁不可重入,同一线程不可嵌套持有读锁(会导致死锁)。 + +**示例:** + +```cpp +ReadWriteLock rwLock; +int sharedValue = 0; + +int ReadValue() { + rwLock.ReadLock(); + int value = sharedValue; + rwLock.ReadUnlock(); + return value; +} +``` + +## 相关文档 + +- [ReadWriteLock 总览](readwritelock.md) - 返回类总览 diff --git a/docs/api/threading/readwritelock/readunlock.md b/docs/api/threading/readwritelock/readunlock.md new file mode 100644 index 0000000..7d2f6be --- /dev/null +++ b/docs/api/threading/readwritelock/readunlock.md @@ -0,0 +1,33 @@ +# ReadWriteLock::ReadUnlock + +```cpp +void ReadUnlock() +``` + +释放读锁。如果这是最后一个读者,将唤醒等待中的写者。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**注意:** 必须与 ReadLock 配对使用,且在持有读锁的线程中调用。 + +**示例:** + +```cpp +ReadWriteLock rwLock; +float sharedData = 0.0f; + +float GetData() { + rwLock.ReadLock(); + float data = sharedData; + rwLock.ReadUnlock(); + return data; +} +``` + +## 相关文档 + +- [ReadWriteLock 总览](readwritelock.md) - 返回类总览 diff --git a/docs/api/threading/readwritelock/readwritelock.md b/docs/api/threading/readwritelock/readwritelock.md new file mode 100644 index 0000000..56f3a4d --- /dev/null +++ b/docs/api/threading/readwritelock/readwritelock.md @@ -0,0 +1,57 @@ +# ReadWriteLock + +**命名空间**: `XCEngine::Threading` + +**类型**: `class` + +**头文件**: `XCEngine/Threading/ReadWriteLock.h` + +**描述**: 读写锁实现,支持多个并发读取或单一写入,提高读多写少场景的并发性能。 + +## 概述 + +`ReadWriteLock` 实现了一个经典的读写锁。它允许多个线程同时持有读锁,但在有写锁时,所有读锁都必须释放,写锁为独占访问。这对于读操作远多于写操作的共享数据非常有效。 + +## 公共方法 + +### 读锁 + +| 方法 | 描述 | +|------|------| +| [`ReadLock`](readlock.md) | 获取读锁(可重入,支持多个并发读者) | +| [`ReadUnlock`](readunlock.md) | 释放读锁 | + +### 写锁 + +| 方法 | 描述 | +|------|------| +| [`WriteLock`](writelock.md) | 获取写锁(独占,阻塞所有读者和写者) | +| [`WriteUnlock`](writeunlock.md) | 释放写锁 | + +## 使用示例 + +```cpp +Threading::ReadWriteLock rwLock; +Containers::HashMap sharedMap; + +// 读操作(多个线程可同时读) +int* ReadData(const String& key) { + rwLock.ReadLock(); + int* value = sharedMap.Find(key); + rwLock.ReadUnlock(); + return value; +} + +// 写操作(独占) +void WriteData(const String& key, int value) { + rwLock.WriteLock(); + sharedMap.Insert(key, value); + rwLock.WriteUnlock(); +} +``` + +## 相关文档 + +- [Mutex](../mutex/mutex.md) - 互斥锁 +- [SpinLock](../spinlock/spinlock.md) - 自旋锁 +- [../threading/threading.md](../threading.md) - 模块总览 diff --git a/docs/api/threading/readwritelock/writelock.md b/docs/api/threading/readwritelock/writelock.md new file mode 100644 index 0000000..0d2af80 --- /dev/null +++ b/docs/api/threading/readwritelock/writelock.md @@ -0,0 +1,35 @@ +# ReadWriteLock::WriteLock + +```cpp +void WriteLock() +``` + +获取写锁(独占)。如果有读者持有锁或有其他写者正在等待,当前线程将阻塞,直到获得独占访问权。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** 平均 O(1),写者饥饿时可能 O(n) + +**注意:** +- 写锁为独占访问,持有期间不允许任何读锁或写锁。 +- 写锁具有优先权,会阻塞后续到达的读者。 +- 同一线程不可重复 WriteLock。 + +**示例:** + +```cpp +ReadWriteLock rwLock; +std::vector buffer; + +void Append(int value) { + rwLock.WriteLock(); + buffer.push_back(value); + rwLock.WriteUnlock(); +} +``` + +## 相关文档 + +- [ReadWriteLock 总览](readwritelock.md) - 返回类总览 diff --git a/docs/api/threading/readwritelock/writeunlock.md b/docs/api/threading/readwritelock/writeunlock.md new file mode 100644 index 0000000..778e6fc --- /dev/null +++ b/docs/api/threading/readwritelock/writeunlock.md @@ -0,0 +1,32 @@ +# ReadWriteLock::WriteUnlock + +```cpp +void WriteUnlock() +``` + +释放写锁。唤醒所有等待中的读者和下一个写者。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**注意:** 必须在持有写锁的线程中调用。 + +**示例:** + +```cpp +ReadWriteLock rwLock; +std::unordered_map cache; + +void UpdateCache(const String& key, int value) { + rwLock.WriteLock(); + cache[key] = value; + rwLock.WriteUnlock(); +} +``` + +## 相关文档 + +- [ReadWriteLock 总览](readwritelock.md) - 返回类总览 diff --git a/docs/api/threading/spinlock/lock.md b/docs/api/threading/spinlock/lock.md new file mode 100644 index 0000000..5917c9d --- /dev/null +++ b/docs/api/threading/spinlock/lock.md @@ -0,0 +1,35 @@ +# SpinLock::Lock + +```cpp +void Lock() +``` + +获取自旋锁。如果锁已被其他线程持有,则使用忙等待(spin)持续轮询,直到获取到锁。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** 平均 O(1),最坏情况取决于竞争程度 + +**注意:** +- 适用于临界区极短(几个 CPU 指令)的场景,避免线程切换开销。 +- 在锁持有时间较长或多核竞争激烈时,会浪费大量 CPU 周期,此时应使用 Mutex。 +- 同一线程不可重复 Lock 同一个 SpinLock。 + +**示例:** + +```cpp +Threading::SpinLock spinLock; +int64_t fastCounter = 0; + +void IncrementFast() { + spinLock.Lock(); + ++fastCounter; + spinLock.Unlock(); +} +``` + +## 相关文档 + +- [SpinLock 总览](spinlock.md) - 返回类总览 diff --git a/docs/api/threading/spinlock/spinlock.md b/docs/api/threading/spinlock/spinlock.md new file mode 100644 index 0000000..c6d2f6d --- /dev/null +++ b/docs/api/threading/spinlock/spinlock.md @@ -0,0 +1,53 @@ +# SpinLock + +**命名空间**: `XCEngine::Threading` + +**类型**: `class` + +**头文件**: `XCEngine/Threading/SpinLock.h` + +**描述**: 自旋锁封装类,使用原子操作实现,适用于保护极短的临界区。 + +## 概述 + +`SpinLock` 是一个轻量级的自旋锁实现,使用 `std::atomic_flag` 的 test-and-set 操作。它在获取锁失败时不断轮询,不会导致线程切换,非常适合保护非常短的临界区(如简单的计数器递增)。 + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Lock`](lock.md) | 获取锁(忙等待) | +| [`Unlock`](unlock.md) | 释放锁 | +| [`TryLock`](trylock.md) | 尝试获取锁(非阻塞) | + +## STL 兼容方法 + +支持 `lock()`, `unlock()`, `try_lock()` 以兼容 STL 的 lockable 概念。**注意**:这些方法为非 `const` 成员函数。 + +## 使用示例 + +```cpp +Threading::SpinLock spinLock; +int counter = 0; + +// 保护极短的临界区 +void FastIncrement() { + spinLock.Lock(); + ++counter; + spinLock.Unlock(); +} + +// TryLock 用法 +void SafeIncrement() { + if (spinLock.TryLock()) { + ++counter; + spinLock.Unlock(); + } +} +``` + +## 相关文档 + +- [Mutex](../mutex/mutex.md) - 互斥锁 +- [ReadWriteLock](../readwritelock/readwritelock.md) - 读写锁 +- [../threading/threading.md](../threading.md) - 模块总览 diff --git a/docs/api/threading/spinlock/trylock.md b/docs/api/threading/spinlock/trylock.md new file mode 100644 index 0000000..f56a41c --- /dev/null +++ b/docs/api/threading/spinlock/trylock.md @@ -0,0 +1,31 @@ +# SpinLock::TryLock + +```cpp +bool TryLock() +``` + +尝试获取自旋锁(非阻塞)。如果锁可用则立即获取并返回 true,否则立即返回 false。 + +**参数:** 无 + +**返回:** `bool` - 获取成功返回 true,锁不可用返回 false + +**复杂度:** O(1) + +**示例:** + +```cpp +Threading::SpinLock spinLock; +int64_t counter = 0; + +void TryIncrement() { + if (spinLock.TryLock()) { + ++counter; + spinLock.Unlock(); + } +} +``` + +## 相关文档 + +- [SpinLock 总览](spinlock.md) - 返回类总览 diff --git a/docs/api/threading/spinlock/unlock.md b/docs/api/threading/spinlock/unlock.md new file mode 100644 index 0000000..01703dd --- /dev/null +++ b/docs/api/threading/spinlock/unlock.md @@ -0,0 +1,32 @@ +# SpinLock::Unlock + +```cpp +void Unlock() +``` + +释放自旋锁,允许其他等待中的线程获取该锁。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**注意:** 必须在持有锁的线程中调用 Unlock。 + +**示例:** + +```cpp +Threading::SpinLock spinLock; +int64_t counter = 0; + +void SafeAdd(int64_t value) { + spinLock.Lock(); + counter += value; + spinLock.Unlock(); +} +``` + +## 相关文档 + +- [SpinLock 总览](spinlock.md) - 返回类总览 diff --git a/docs/api/threading/task-group/adddependency.md b/docs/api/threading/task-group/adddependency.md new file mode 100644 index 0000000..94829a4 --- /dev/null +++ b/docs/api/threading/task-group/adddependency.md @@ -0,0 +1,44 @@ +# TaskGroup::AddDependency + +```cpp +void AddDependency(uint64_t taskId, uint64_t dependsOn) +``` + +为任务添加依赖关系。被依赖的任务必须先完成,当前任务才会开始执行。 + +**参数:** +- `taskId` - 任务 ID(需要等待的任务) +- `dependsOn` - 依赖的父任务 ID + +**返回:** 无 + +**复杂度:** O(1) + +**注意:** +- 如果被依赖的任务不存在或已完成,调用无效果。 +- 支持添加多个依赖,但不支持循环依赖。 + +**示例:** + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); + +uint64_t init = group->AddTask([]() { Initialize(); }); +uint64_t task1 = group->AddTask([]() { Phase1(); }); +uint64_t task2 = group->AddTask([]() { Phase2(); }); +uint64_t cleanup = group->AddTask([]() { Cleanup(); }); + +// task1 和 task2 依赖 init +group->AddDependency(task1, init); +group->AddDependency(task2, init); + +// cleanup 依赖 task1 和 task2 +group->AddDependency(cleanup, task1); +group->AddDependency(cleanup, task2); + +group->Wait(); +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 diff --git a/docs/api/threading/task-group/addtask.md b/docs/api/threading/task-group/addtask.md new file mode 100644 index 0000000..53dadbe --- /dev/null +++ b/docs/api/threading/task-group/addtask.md @@ -0,0 +1,60 @@ +# TaskGroup::AddTask + +添加任务到任务组。有两个重载版本。 + +## 重载 1: 添加 ITask 对象 + +```cpp +uint64_t AddTask(std::unique_ptr task) +``` + +将一个已有的 ITask 对象添加到任务组。 + +**参数:** +- `task` - 要添加的 unique_ptr 任务对象 + +**返回:** `uint64_t` - 分配的任务 ID + +**复杂度:** O(1) + +## 重载 2: 添加 lambda 任务 + +```cpp +uint64_t AddTask(Callback&& func, TaskPriority priority = TaskPriority::Normal) +``` + +将一个 lambda 函数包装为任务添加到任务组。 + +**参数:** +- `func` - 要执行的可调用对象 +- `priority` - 任务优先级,默认 TaskPriority::Normal + +**返回:** `uint64_t` - 分配的任务 ID + +**复杂度:** O(1) + +**示例:** + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); + +// 添加 lambda 任务 +uint64_t id1 = group->AddTask([]() { + printf("Task A running\n"); +}); + +uint64_t id2 = group->AddTask([]() { + printf("Task B running\n"); +}, TaskPriority::High); + +// 添加自定义 ITask +class MyTask : public ITask { +public: + void Execute() override { printf("Custom task\n"); } +}; +uint64_t id3 = group->AddTask(std::make_unique()); +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 diff --git a/docs/api/threading/task-group/cancel.md b/docs/api/threading/task-group/cancel.md new file mode 100644 index 0000000..a7a55da --- /dev/null +++ b/docs/api/threading/task-group/cancel.md @@ -0,0 +1,45 @@ +# TaskGroup::Cancel + +```cpp +void Cancel() +``` + +**注意:** 此方法为**部分实现**,存在已知问题。 + +取消任务组中所有尚未执行的任务。正在执行的任务将不受影响。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n) + +**当前状态:** 此方法会调用各任务的 `OnCancel()` 回调,但不会减少 `m_pendingCount` 计数器。因此调用 `Wait()` 会导致永久阻塞。建议在 `Cancel()` 后使用 `IsComplete()` 轮询或使用带超时的 `WaitFor()`。 + +**示例:** + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); + +for (int i = 0; i < 100; ++i) { + group->AddTask([i]() { + if (ShouldCancel()) { + return; // 检查取消状态 + } + ProcessLongTask(i); + }); +} + +// 如果用户点击取消按钮 +if (userClickedCancel) { + group->Cancel(); + printf("Tasks canceled. Progress: %.1f%%\n", group->GetProgress() * 100.0f); +} + +// 注意:Cancel() 后 Wait() 会永久阻塞,应使用 WaitFor() +group->WaitFor(std::chrono::seconds(1)); +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 diff --git a/docs/api/threading/task-group/getprogress.md b/docs/api/threading/task-group/getprogress.md new file mode 100644 index 0000000..bf69546 --- /dev/null +++ b/docs/api/threading/task-group/getprogress.md @@ -0,0 +1,40 @@ +# TaskGroup::GetProgress + +```cpp +float GetProgress() const +``` + +**注意:** 此方法当前为**空实现/桩代码**。 + +获取任务组的完成进度。 + +**参数:** 无 + +**返回:** `float` - 始终返回 `0.0f`(任务组为空时返回 `1.0f`) + +**复杂度:** O(1) + +**当前状态:** 此方法为空实现,始终返回 `0.0f`,因为 `m_completedCount` 未被更新。 + +**示例:** + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); + +for (int i = 0; i < 1000; ++i) { + group->AddTask([i]() { ProcessItem(i); }); +} + +// 显示进度(注意:当前实现始终返回 0.0f) +while (!group->IsComplete()) { + float progress = group->GetProgress(); + printf("\rProgress: %.1f%%", progress * 100.0f); + Thread::Sleep(100); +} +printf("\n"); +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 +- [IsComplete](iscomplete.md) - 检查是否完成 diff --git a/docs/api/threading/task-group/iscomplete.md b/docs/api/threading/task-group/iscomplete.md new file mode 100644 index 0000000..9c8d0ea --- /dev/null +++ b/docs/api/threading/task-group/iscomplete.md @@ -0,0 +1,38 @@ +# TaskGroup::IsComplete + +```cpp +bool IsComplete() const +``` + +**注意:** 此方法当前为**空实现/桩代码**。 + +检查任务组中所有任务是否已完成。 + +**参数:** 无 + +**返回:** `bool` - 始终返回 `false`(空实现) + +**复杂度:** O(1)(空实现) + +**当前状态:** 此方法为空实现,始终返回 `false`,因为 `m_pendingCount` 计数器未正确递减。 + +**示例:** + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); + +for (int i = 0; i < 100; ++i) { + group->AddTask([i]() { HeavyCompute(i); }); +} + +// 非阻塞轮询 +while (!group->IsComplete()) { + printf("Progress: %.1f%%\n", group->GetProgress() * 100.0f); + Thread::Sleep(500); +} +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 +- [GetProgress](getprogress.md) - 获取完成进度 diff --git a/docs/api/threading/task-group/setcompletecallback.md b/docs/api/threading/task-group/setcompletecallback.md new file mode 100644 index 0000000..45256a4 --- /dev/null +++ b/docs/api/threading/task-group/setcompletecallback.md @@ -0,0 +1,36 @@ +# TaskGroup::SetCompleteCallback + +```cpp +void SetCompleteCallback(Callback&& callback) +``` + +设置任务组完成回调。当所有任务都完成后,回调函数将在某个工作线程中被调用。 + +**参数:** +- `callback` - 完成时要调用的回调函数 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); + +group->AddTask([]() { LoadTextures(); }); +group->AddTask([]() { LoadMeshes(); }); +group->AddTask([]() { LoadAudio(); }); + +group->SetCompleteCallback([]() { + printf("All assets loaded!\n"); + ResourceManager::InitGPUResources(); +}); + +group->Wait(); +TaskSystem::Get().DestroyTaskGroup(group); +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 diff --git a/docs/api/threading/task-group/task-group.md b/docs/api/threading/task-group/task-group.md new file mode 100644 index 0000000..646e6c3 --- /dev/null +++ b/docs/api/threading/task-group/task-group.md @@ -0,0 +1,66 @@ +# TaskGroup + +**命名空间**: `XCEngine::Threading` + +**类型**: `class` + +**头文件**: `XCEngine/Threading/TaskGroup.h` + +**描述**: 任务组管理类,用于组织多个任务并支持批量等待、进度跟踪和依赖管理。 + +## 概述 + +`TaskGroup` 提供了一种批量管理任务的机制。它允许添加多个任务、设置任务依赖关系、等待所有任务完成,并提供进度回调功能。 + +## 公共类型 + +| 类型 | 描述 | +|------|------| +| `Callback = std::function` | 任务组回调函数类型 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `TaskGroup()` | 默认构造函数 | +| `~TaskGroup()` | 析构函数 | +| [`AddTask(unique_ptr)`](addtask.md) | 添加任务对象 | +| [`AddTask(callback)`](addtask.md) | 添加 lambda 任务 | +| [`AddDependency`](adddependency.md) | 添加任务依赖关系 | +| [`Wait`](wait.md) | 阻塞等待所有任务完成 | +| [`WaitFor`](waitfor.md) | 超时等待 | +| [`SetCompleteCallback`](setcompletecallback.md) | 设置完成回调 | +| [`IsComplete`](iscomplete.md) | 检查所有任务是否完成 | +| [`GetProgress`](getprogress.md) | 获取完成进度(0.0f ~ 1.0f) | +| [`Cancel`](cancel.md) | 取消所有任务 | + +## 使用示例 + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); + +// 添加多个任务 +uint64_t task1 = group->AddTask([]() { /* 任务1 */ }); +uint64_t task2 = group->AddTask([]() { /* 任务2 */ }); + +// 设置依赖:task3 等待 task1 完成 +uint64_t task3 = group->AddTask([]() { /* 任务3 */ }); +group->AddDependency(task3, task1); + +// 设置完成回调 +group->SetCompleteCallback([]() { + printf("All tasks completed!\n"); +}); + +// 等待完成 +group->Wait(); + +// 销毁 +TaskSystem::Get().DestroyTaskGroup(group); +``` + +## 相关文档 + +- [ITask](../task/task.md) - 任务基类 +- [TaskSystem](../task-system/task-system.md) - 任务系统 +- [../threading/threading.md](../threading.md) - 模块总览 diff --git a/docs/api/threading/task-group/wait.md b/docs/api/threading/task-group/wait.md new file mode 100644 index 0000000..0d8765e --- /dev/null +++ b/docs/api/threading/task-group/wait.md @@ -0,0 +1,46 @@ +# TaskGroup::Wait + +```cpp +void Wait() +``` + +**注意:** 此方法当前为**空实现/桩代码**,不执行任何操作。 + +阻塞当前线程,等待任务组中所有任务完成。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** N/A(空实现) + +**当前状态:** 此方法为空实现,不执行任何操作。由于 `m_pendingCount` 计数器未正确更新,此方法永远无法正常运作。 + +**建议:** 使用 `WaitFor()` 代替以避免永久阻塞。 + +**示例:** + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); + +for (int i = 0; i < 10; ++i) { + group->AddTask([i]() { + printf("Task %d running\n", i); + }); +} + +printf("Waiting for all tasks...\n"); +// 注意:Wait() 为空实现,建议使用 WaitFor() +if (group->WaitFor(std::chrono::seconds(5))) { + printf("All tasks completed within 5 seconds\n"); +} else { + printf("Timeout! Tasks may not have completed\n"); +} + +TaskSystem::Get().DestroyTaskGroup(group); +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 +- [WaitFor](waitfor.md) - 超时等待 diff --git a/docs/api/threading/task-group/waitfor.md b/docs/api/threading/task-group/waitfor.md new file mode 100644 index 0000000..f64c42f --- /dev/null +++ b/docs/api/threading/task-group/waitfor.md @@ -0,0 +1,39 @@ +# TaskGroup::WaitFor + +```cpp +bool WaitFor(std::chrono::milliseconds timeout) +``` + +等待任务组中所有任务完成,可在超时后返回。 + +**参数:** +- `timeout` - 最大等待时间 + +**返回:** `bool` - 所有任务在超时前完成返回 true,超时返回 false + +**复杂度:** O(n) + +**示例:** + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); + +for (int i = 0; i < 5; ++i) { + group->AddTask([i]() { + Thread::Sleep(i * 100); + printf("Task %d done\n", i); + }); +} + +if (group->WaitFor(std::chrono::seconds(1))) { + printf("All tasks completed within 1 second\n"); +} else { + printf("Timeout! Some tasks still running\n"); + printf("Progress: %.1f%%\n", group->GetProgress() * 100.0f); +} +``` + +## 相关文档 + +- [TaskGroup 总览](task-group.md) - 返回类总览 +- [Wait](wait.md) - 无超时等待 diff --git a/docs/api/threading/task-system/createtaskgroup.md b/docs/api/threading/task-system/createtaskgroup.md new file mode 100644 index 0000000..6232ca4 --- /dev/null +++ b/docs/api/threading/task-system/createtaskgroup.md @@ -0,0 +1,39 @@ +# TaskSystem::CreateTaskGroup + +```cpp +TaskGroup* CreateTaskGroup() +``` + +创建一个任务组用于批量管理多个任务。 + +**参数:** 无 + +**返回:** `TaskGroup*` - 新创建的任务组指针 + +**复杂度:** O(1) + +**注意:** +- 任务组必须通过 DestroyTaskGroup 显式销毁。 +- 任务组的所有权归调用者,TaskSystem 不负责销毁。 + +**示例:** + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); + +group->AddTask([]() { LoadTextures(); }); +group->AddTask([]() { LoadModels(); }); +group->AddTask([]() { LoadAudio(); }); + +group->SetCompleteCallback([]() { + printf("All resources loaded!\n"); +}); + +group->Wait(); +TaskSystem::Get().DestroyTaskGroup(group); +``` + +## 相关文档 + +- [TaskSystem 总览](task-system.md) - 返回类总览 +- [DestroyTaskGroup](destroytaskgroup.md) - 销毁任务组 diff --git a/docs/api/threading/task-system/destroytaskgroup.md b/docs/api/threading/task-system/destroytaskgroup.md new file mode 100644 index 0000000..cc362db --- /dev/null +++ b/docs/api/threading/task-system/destroytaskgroup.md @@ -0,0 +1,32 @@ +# TaskSystem::DestroyTaskGroup + +```cpp +void DestroyTaskGroup(TaskGroup* group) +``` + +销毁一个任务组并释放其资源。 + +**参数:** +- `group` - 要销毁的任务组指针 + +**返回:** 无 + +**复杂度:** O(1) + +**注意:** +- 销毁时如果还有未完成的任务,这些任务将被取消。 +- 传入 nullptr 无效果。 + +**示例:** + +```cpp +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); +// ... 添加任务 ... + +TaskSystem::Get().DestroyTaskGroup(group); +``` + +## 相关文档 + +- [TaskSystem 总览](task-system.md) - 返回类总览 +- [CreateTaskGroup](createtaskgroup.md) - 创建任务组 diff --git a/docs/api/threading/task-system/get.md b/docs/api/threading/task-system/get.md new file mode 100644 index 0000000..a6d22f7 --- /dev/null +++ b/docs/api/threading/task-system/get.md @@ -0,0 +1,26 @@ +# TaskSystem::Get + +```cpp +static TaskSystem& Get() +``` + +获取 TaskSystem 单例实例。第一次调用时创建单例。 + +**参数:** 无 + +**返回:** `TaskSystem&` - 单例实例的引用 + +**复杂度:** O(1) + +**线程安全:** 线程安全 + +**示例:** + +```cpp +TaskSystem& system = TaskSystem::Get(); +system.Initialize(config); +``` + +## 相关文档 + +- [TaskSystem 总览](task-system.md) - 返回类总览 diff --git a/docs/api/threading/task-system/getworkerthreadcount.md b/docs/api/threading/task-system/getworkerthreadcount.md new file mode 100644 index 0000000..d9ba16f --- /dev/null +++ b/docs/api/threading/task-system/getworkerthreadcount.md @@ -0,0 +1,25 @@ +# TaskSystem::GetWorkerThreadCount + +```cpp +uint32_t GetWorkerThreadCount() const +``` + +获取工作线程的数量。 + +**参数:** 无 + +**返回:** `uint32_t` - 工作线程数量 + +**复杂度:** O(1) + +**示例:** + +```cpp +TaskSystem::Get().Initialize(config); +uint32_t count = TaskSystem::Get().GetWorkerThreadCount(); +printf("Worker threads: %u\n", count); +``` + +## 相关文档 + +- [TaskSystem 总览](task-system.md) - 返回类总览 diff --git a/docs/api/threading/task-system/initialize.md b/docs/api/threading/task-system/initialize.md new file mode 100644 index 0000000..82ca1a0 --- /dev/null +++ b/docs/api/threading/task-system/initialize.md @@ -0,0 +1,37 @@ +# TaskSystem::Initialize + +```cpp +void Initialize(const TaskSystemConfig& config) +``` + +初始化任务系统,创建工作线程并启动任务调度。 + +**参数:** +- `config` - 任务系统配置(参见 TaskSystemConfig) + +**返回:** 无 + +**复杂度:** O(n),n 为 workerThreadCount + +**注意:** +- 多次调用将先关闭已有系统再重新初始化。 +- 应在主线程中调用,在任何任务提交之前完成初始化。 + +**示例:** + +```cpp +TaskSystemConfig config; +config.workerThreadCount = std::thread::hardware_concurrency(); +config.enableTaskProfiling = true; // 预留配置项(当前未使用) +config.stealTasks = true; // 预留配置项(当前未实现) +config.maxTaskQueueSize = 2048; // 预留配置项(当前未强制限制) + +TaskSystem::Get().Initialize(config); +printf("TaskSystem started with %u workers\n", + TaskSystem::Get().GetWorkerThreadCount()); +``` + +## 相关文档 + +- [TaskSystem 总览](task-system.md) - 返回类总览 +- [Shutdown](shutdown.md) - 关闭任务系统 diff --git a/docs/api/threading/task-system/parallelfor.md b/docs/api/threading/task-system/parallelfor.md new file mode 100644 index 0000000..589aecc --- /dev/null +++ b/docs/api/threading/task-system/parallelfor.md @@ -0,0 +1,46 @@ +# TaskSystem::ParallelFor + +```cpp +template +void ParallelFor(int32_t start, int32_t end, Func&& func) +``` + +并行执行 for 循环。将循环范围划分为多个块,分配给多个工作线程并行处理。 + +**模板参数:** +- `Func` - 可调用对象类型,签名为 `void(int32_t)` + +**参数:** +- `start` - 循环起始索引(包含) +- `end` - 循环结束索引(不包含) +- `func` - 对每个索引执行的函数 + +**返回:** 无 + +**复杂度:** O(n) + +**分区策略:** +- 根据 `std::thread::hardware_concurrency()` 确定线程数。 +- 将范围均分给各线程,每个线程处理连续的块。 + +**示例:** + +```cpp +// 并行处理 10000 个元素 +std::vector data(10000, 0.0f); + +TaskSystem::Get().ParallelFor(0, 10000, [&data](int32_t i) { + data[i] = std::sin(i * 0.01f) * std::cos(i * 0.007f); +}); + +// 并行矩阵乘法 +TaskSystem::Get().ParallelFor(0, N, [&matrix](int32_t row) { + for (int32_t col = 0; col < N; ++col) { + matrix[row * N + col] = Compute(row, col); + } +}); +``` + +## 相关文档 + +- [TaskSystem 总览](task-system.md) - 返回类总览 diff --git a/docs/api/threading/task-system/runonmainthread.md b/docs/api/threading/task-system/runonmainthread.md new file mode 100644 index 0000000..5afc149 --- /dev/null +++ b/docs/api/threading/task-system/runonmainthread.md @@ -0,0 +1,43 @@ +# TaskSystem::RunOnMainThread + +```cpp +void RunOnMainThread(std::function&& func) +``` + +将任务提交到主线程队列。在主线程中调用 Update 时执行。 + +**参数:** +- `func` - 要在主线程执行的函数 + +**返回:** 无 + +**复杂度:** O(1) + +**使用场景:** +- 从工作线程回调需要更新 UI 或访问主线程资源。 +- 避免跨线程数据竞争。 + +**示例:** + +```cpp +// 在工作线程中 +void WorkerThreadCode() { + int result = HeavyCompute(); + + // 将结果发送到主线程更新 UI + TaskSystem::Get().RunOnMainThread([result]() { + UI.UpdateResult(result); + }); +} + +// 在主线程中 +while (running) { + TaskSystem::Get().Update(); // 处理主线程任务 + RenderFrame(); +} +``` + +## 相关文档 + +- [TaskSystem 总览](task-system.md) - 返回类总览 +- [Update](update.md) - 处理主线程队列 diff --git a/docs/api/threading/task-system/shutdown.md b/docs/api/threading/task-system/shutdown.md new file mode 100644 index 0000000..6d1d0c4 --- /dev/null +++ b/docs/api/threading/task-system/shutdown.md @@ -0,0 +1,33 @@ +# TaskSystem::Shutdown + +```cpp +void Shutdown() +``` + +关闭任务系统,停止所有工作线程并清理资源。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n) + +**注意:** +- 调用后应等待所有提交的任务执行完毕,或确保不再需要未完成的任务。 +- 关闭后不可再次使用,必须重新 Initialize。 + +**示例:** + +```cpp +TaskSystem::Get().Initialize(config); + +// ... 使用任务系统 ... + +TaskSystem::Get().Shutdown(); +printf("TaskSystem stopped\n"); +``` + +## 相关文档 + +- [TaskSystem 总览](task-system.md) - 返回类总览 +- [Initialize](initialize.md) - 初始化任务系统 diff --git a/docs/api/threading/task-system/submit.md b/docs/api/threading/task-system/submit.md new file mode 100644 index 0000000..beafa89 --- /dev/null +++ b/docs/api/threading/task-system/submit.md @@ -0,0 +1,63 @@ +# TaskSystem::Submit + +将任务提交到任务系统调度执行。有两个重载版本。 + +## 重载 1: 提交 ITask 对象 + +```cpp +uint64_t Submit(std::unique_ptr task) +``` + +提交一个 ITask 对象到任务队列。 + +**参数:** +- `task` - 要提交的任务对象 + +**返回:** `uint64_t` - 分配的任务 ID + +**复杂度:** O(log n) + +## 重载 2: 提交 lambda 任务 + +```cpp +uint64_t Submit(std::function&& func, TaskPriority priority = TaskPriority::Normal) +``` + +将可调用对象包装为任务提交。 + +**参数:** +- `func` - 要执行的可调用对象 +- `priority` - 任务优先级,默认 TaskPriority::Normal + +**返回:** `uint64_t` - 分配的任务 ID + +**复杂度:** O(log n) + +**示例:** + +```cpp +// 提交自定义任务 +class MyTask : public ITask { +public: + void Execute() override { printf("MyTask running\n"); } +}; +uint64_t id1 = TaskSystem::Get().Submit(std::make_unique()); + +// 提交 lambda +uint64_t id2 = TaskSystem::Get().Submit([]() { + printf("Lambda task\n"); +}); + +uint64_t id3 = TaskSystem::Get().Submit([]() { + HeavyCompute(); +}, TaskPriority::High); + +// 等待任务完成 +TaskSystem::Get().Wait(id1); +TaskSystem::Get().Wait(id2); +TaskSystem::Get().Wait(id3); +``` + +## 相关文档 + +- [TaskSystem 总览](task-system.md) - 返回类总览 diff --git a/docs/api/threading/task-system/task-system.md b/docs/api/threading/task-system/task-system.md new file mode 100644 index 0000000..dc40ef7 --- /dev/null +++ b/docs/api/threading/task-system/task-system.md @@ -0,0 +1,82 @@ +# TaskSystem + +**命名空间**: `XCEngine::Threading` + +**类型**: `class` (singleton) + +**头文件**: `XCEngine/Threading/TaskSystem.h` + +**描述**: 并行任务调度系统单例,提供优先级任务队列。 + +## 概述 + +`TaskSystem` 是 XCEngine 的核心并行任务调度系统。它创建多个工作线程,使用优先级队列调度任务。它还提供 `ParallelFor` 方法用于数据级并行,以及主线程任务队列。 + +**注意:** 当前实现的 `stealTasks` 配置项未生效,任务系统使用单一全局任务队列而非工作窃取模式。 + +## 单例访问 + +| 方法 | 描述 | +|------|------| +| [`Get`](get.md) | 获取单例实例 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| [`Get`](get.md) | 获取单例实例 | +| [`Initialize`](initialize.md) | 初始化任务系统 | +| [`Shutdown`](shutdown.md) | 关闭任务系统 | +| [`Submit(unique_ptr)`](submit.md) | 提交任务对象 | +| [`Submit(callback)`](submit.md) | 提交 lambda 任务 | +| [`CreateTaskGroup`](createtaskgroup.md) | 创建任务组 | +| [`DestroyTaskGroup`](destroytaskgroup.md) | 销毁任务组 | +| [`Wait`](wait.md) | 等待指定任务完成(当前为空实现) | +| [`GetWorkerThreadCount`](getworkerthreadcount.md) | 获取工作线程数量 | +| [`ParallelFor`](parallelfor.md) | 并行执行 for 循环 | +| [`RunOnMainThread`](runonmainthread.md) | 将任务提交到主线程执行 | +| [`Update`](update.md) | 在主线程中处理主线程队列 | + +## 使用示例 + +```cpp +// 初始化(4 个工作线程) +TaskSystemConfig config; +config.workerThreadCount = 4; +TaskSystem::Get().Initialize(config); + +// 提交任务 +TaskSystem::Get().Submit([]() { + printf("Task 1 running\n"); +}); + +TaskSystem::Get().Submit([]() { + printf("Task 2 running\n"); +}, TaskPriority::High); + +// 并行 for +TaskSystem::Get().ParallelFor(0, 1000, [](int32_t i) { + process(i); +}); + +// 主线程任务 +TaskSystem::Get().RunOnMainThread([]() { + // 更新 UI 或其他主线程操作 +}); + +// 主循环中调用 Update +while (running) { + TaskSystem::Get().Update(); // 处理主线程任务 +} + +// 关闭 +TaskSystem::Get().Shutdown(); +``` + +## 相关文档 + +- [ITask](../task/task.md) - 任务基类 +- [LambdaTask](../lambdatask/lambdatask.md) - Lambda 任务 +- [TaskGroup](../task-group/task-group.md) - 任务组 +- [TaskSystemConfig](../tasksystemconfig/tasksystemconfig.md) - 配置 +- [../threading/threading.md](../threading.md) - 模块总览 diff --git a/docs/api/threading/task-system/update.md b/docs/api/threading/task-system/update.md new file mode 100644 index 0000000..adfe429 --- /dev/null +++ b/docs/api/threading/task-system/update.md @@ -0,0 +1,36 @@ +# TaskSystem::Update + +```cpp +void Update() +``` + +在主线程中处理主线程队列。执行所有通过 RunOnMainThread 提交的任务。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n),n 为队列中待执行任务数 + +**使用场景:** +- 在主循环中调用,确保 RunOnMainThread 提交的任务能够执行。 +- 应在渲染前调用。 + +**示例:** + +```cpp +// 主循环 +while (application.IsRunning()) { + TaskSystem::Get().Update(); // 处理主线程任务 + + // 渲染 + Renderer.BeginFrame(); + RenderScene(); + Renderer.EndFrame(); +} +``` + +## 相关文档 + +- [TaskSystem 总览](task-system.md) - 返回类总览 +- [RunOnMainThread](runonmainthread.md) - 提交主线程任务 diff --git a/docs/api/threading/task-system/wait.md b/docs/api/threading/task-system/wait.md new file mode 100644 index 0000000..d6e2e7d --- /dev/null +++ b/docs/api/threading/task-system/wait.md @@ -0,0 +1,37 @@ +# TaskSystem::Wait + +```cpp +void Wait(uint64_t taskId) +``` + +**注意:** 此方法当前为空实现,不执行任何操作。 + +**参数:** +- `taskId` - 要等待的任务 ID + +**返回:** 无 + +**复杂度:** N/A(空实现) + +**当前状态:** 此方法为空实现,不执行任何操作。任务系统目前不支持按任务 ID 等待。 + +**建议:** 使用 `TaskGroup::Wait` 代替此方法。 + +**示例:** + +```cpp +uint64_t id = TaskSystem::Get().Submit([]() { + for (int i = 0; i < 1000000; ++i) { + Compute(i); + } +}); + +printf("Waiting for task...\n"); +// 注意:当前实现为空,建议使用 TaskGroup 来等待任务完成 +TaskSystem::Get().Wait(id); +printf("Task completed\n"); +``` + +## 相关文档 + +- [TaskSystem 总览](task-system.md) - 返回类总览 diff --git a/docs/api/threading/task/addref.md b/docs/api/threading/task/addref.md new file mode 100644 index 0000000..114fd61 --- /dev/null +++ b/docs/api/threading/task/addref.md @@ -0,0 +1,27 @@ +# ITask::AddRef + +```cpp +void AddRef() +``` + +增加任务的引用计数。用于延长任务的生命周期,使其不会被自动释放。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +ITask* task = new MyTask(); +task->AddRef(); // 保持引用,不会在 Release 时被删除 +task->SetPriority(TaskPriority::High); +TaskSystem::Get().Submit(std::unique_ptr(task)); +``` + +## 相关文档 + +- [ITask 总览](task.md) - 返回类总览 +- [Release](release.md) - 释放引用计数 diff --git a/docs/api/threading/task/execute.md b/docs/api/threading/task/execute.md new file mode 100644 index 0000000..476730e --- /dev/null +++ b/docs/api/threading/task/execute.md @@ -0,0 +1,43 @@ +# ITask::Execute + +```cpp +virtual void Execute() = 0 +``` + +任务执行逻辑(纯虚方法)。用户必须在派生类中实现此方法以定义任务的具体行为。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** 取决于具体任务实现 + +**注意:** +- 此方法由 TaskSystem 的工作线程调用。 +- 任务执行期间如发生未捕获异常,行为未定义。 + +**示例:** + +```cpp +class ComputeTask : public ITask { +public: + explicit ComputeTask(int n) : m_n(n) {} + + void Execute() override { + int result = 0; + for (int i = 0; i < m_n; ++i) { + result += i; + } + printf("Result: %d\n", result); + } + +private: + int m_n; +}; + +TaskSystem::Get().Submit(std::make_unique(100)); +``` + +## 相关文档 + +- [ITask 总览](task.md) - 返回类总览 diff --git a/docs/api/threading/task/getid.md b/docs/api/threading/task/getid.md new file mode 100644 index 0000000..8a40ad3 --- /dev/null +++ b/docs/api/threading/task/getid.md @@ -0,0 +1,25 @@ +# ITask::GetId + +```cpp +uint64_t GetId() const +``` + +获取任务的唯一标识符。 + +**参数:** 无 + +**返回:** `uint64_t` - 任务的唯一 ID + +**复杂度:** O(1) + +**示例:** + +```cpp +ITask* task = /* ... */; +uint64_t id = task->GetId(); +printf("Task ID: %llu\n", (unsigned long long)id); +``` + +## 相关文档 + +- [ITask 总览](task.md) - 返回类总览 diff --git a/docs/api/threading/task/getpriority.md b/docs/api/threading/task/getpriority.md new file mode 100644 index 0000000..c88c0e8 --- /dev/null +++ b/docs/api/threading/task/getpriority.md @@ -0,0 +1,27 @@ +# ITask::GetPriority + +```cpp +TaskPriority GetPriority() const +``` + +获取任务的优先级。 + +**参数:** 无 + +**返回:** `TaskPriority` - 当前任务的优先级 + +**复杂度:** O(1) + +**示例:** + +```cpp +ITask* task = /* ... */; +TaskPriority priority = task->GetPriority(); +if (priority == TaskPriority::Critical) { + printf("Critical task\n"); +} +``` + +## 相关文档 + +- [ITask 总览](task.md) - 返回类总览 diff --git a/docs/api/threading/task/getstatus.md b/docs/api/threading/task/getstatus.md new file mode 100644 index 0000000..f0ae485 --- /dev/null +++ b/docs/api/threading/task/getstatus.md @@ -0,0 +1,32 @@ +# ITask::GetStatus + +```cpp +TaskStatus GetStatus() const +``` + +获取任务的当前状态。 + +**参数:** 无 + +**返回:** `TaskStatus` - 当前任务状态 + +**复杂度:** O(1) + +**示例:** + +```cpp +ITask* task = /* ... */; +TaskStatus status = task->GetStatus(); +switch (status) { + case TaskStatus::Pending: printf("Pending\n"); break; + case TaskStatus::Scheduled: printf("Scheduled\n"); break; + case TaskStatus::Running: printf("Running\n"); break; + case TaskStatus::Completed: printf("Completed\n"); break; + case TaskStatus::Failed: printf("Failed\n"); break; + case TaskStatus::Canceled: printf("Canceled\n"); break; +} +``` + +## 相关文档 + +- [ITask 总览](task.md) - 返回类总览 diff --git a/docs/api/threading/task/oncancel.md b/docs/api/threading/task/oncancel.md new file mode 100644 index 0000000..02c7ff1 --- /dev/null +++ b/docs/api/threading/task/oncancel.md @@ -0,0 +1,38 @@ +# ITask::OnCancel + +```cpp +virtual void OnCancel() +``` + +任务取消回调。可在派生类中重写此方法,以在任务被取消时执行清理操作。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** 取决于具体实现 + +**示例:** + +```cpp +class NetworkTask : public ITask { +public: + void Execute() override { + for (int i = 0; i < 100; ++i) { + if (GetStatus() == TaskStatus::Canceled) { + return; + } + SendPacket(i); + } + } + + void OnCancel() override { + CloseConnection(); + printf("Network task canceled\n"); + } +}; +``` + +## 相关文档 + +- [ITask 总览](task.md) - 返回类总览 diff --git a/docs/api/threading/task/oncomplete.md b/docs/api/threading/task/oncomplete.md new file mode 100644 index 0000000..3191a6a --- /dev/null +++ b/docs/api/threading/task/oncomplete.md @@ -0,0 +1,39 @@ +# ITask::OnComplete + +```cpp +virtual void OnComplete() +``` + +任务完成回调。可在派生类中重写此方法,以在任务执行完毕后执行清理或后续操作。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** 取决于具体实现 + +**示例:** + +```cpp +class DataLoadTask : public ITask { +public: + explicit DataLoadTask(const String& path) : m_path(path) {} + + void Execute() override { + m_data = LoadFromFile(m_path); + } + + void OnComplete() override { + printf("Data loaded, size: %zu\n", m_data.Size()); + ProcessData(m_data); + } + +private: + String m_path; + Containers::Vector m_data; +}; +``` + +## 相关文档 + +- [ITask 总览](task.md) - 返回类总览 diff --git a/docs/api/threading/task/release.md b/docs/api/threading/task/release.md new file mode 100644 index 0000000..f06c866 --- /dev/null +++ b/docs/api/threading/task/release.md @@ -0,0 +1,32 @@ +# ITask::Release + +```cpp +void Release() +``` + +减少引用计数。当引用计数归零时,对象会自动 delete 自身。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**注意:** +- 任务提交给 TaskSystem 后,TaskSystem 会自动管理引用计数。 +- 当任务完成且无人持有引用时,任务对象将被自动销毁。 +- 不要在任务执行过程中调用 Release。 + +**示例:** + +```cpp +ITask* task = new MyTask(); +task->AddRef(); // 引用计数 = 2 +TaskSystem::Get().Submit(std::unique_ptr(task)); // 引用计数 = 1 +task->Release(); // 引用计数 = 0,任务被 delete +``` + +## 相关文档 + +- [ITask 总览](task.md) - 返回类总览 +- [AddRef](addref.md) - 增加引用计数 diff --git a/docs/api/threading/task/setid.md b/docs/api/threading/task/setid.md new file mode 100644 index 0000000..adeda81 --- /dev/null +++ b/docs/api/threading/task/setid.md @@ -0,0 +1,28 @@ +# ITask::SetId + +```cpp +void SetId(uint64_t id) +``` + +设置任务的唯一标识符。通常由 TaskSystem 在提交时自动分配。 + +**参数:** +- `id` - 要设置的唯一标识符 + +**返回:** 无 + +**复杂度:** O(1) + +**示例:** + +```cpp +class MyTask : public ITask { +public: + MyTask() { SetId(GenerateId()); } + void Execute() override { /* ... */ } +}; +``` + +## 相关文档 + +- [ITask 总览](task.md) - 返回类总览 diff --git a/docs/api/threading/task/setpriority.md b/docs/api/threading/task/setpriority.md new file mode 100644 index 0000000..eb0efde --- /dev/null +++ b/docs/api/threading/task/setpriority.md @@ -0,0 +1,28 @@ +# ITask::SetPriority + +```cpp +void SetPriority(TaskPriority priority) +``` + +设置任务的优先级。 + +**参数:** +- `priority` - 新的优先级(参见 TaskPriority 枚举) + +**返回:** 无 + +**复杂度:** O(1) + +**注意:** 任务提交后修改优先级可能不会立即生效,取决于任务系统实现。 + +**示例:** + +```cpp +auto task = std::make_unique(); +task->SetPriority(TaskPriority::High); +TaskSystem::Get().Submit(std::move(task)); +``` + +## 相关文档 + +- [ITask 总览](task.md) - 返回类总览 diff --git a/docs/api/threading/task/setstatus.md b/docs/api/threading/task/setstatus.md new file mode 100644 index 0000000..d3da148 --- /dev/null +++ b/docs/api/threading/task/setstatus.md @@ -0,0 +1,35 @@ +# ITask::SetStatus + +```cpp +void SetStatus(TaskStatus status) +``` + +设置任务的当前状态。 + +**参数:** +- `status` - 新的状态(参见 TaskStatus 枚举) + +**返回:** 无 + +**复杂度:** O(1) + +**注意:** 正常情况下由 TaskSystem 管理状态。手动设置状态可能干扰任务系统的正常调度。 + +**示例:** + +```cpp +class ConditionalTask : public ITask { +public: + void Execute() override { + if (someCondition) { + SetStatus(TaskStatus::Failed); + return; + } + // 正常处理 + } +}; +``` + +## 相关文档 + +- [ITask 总览](task.md) - 返回类总览 diff --git a/docs/api/threading/task/task.md b/docs/api/threading/task/task.md new file mode 100644 index 0000000..4b33cf8 --- /dev/null +++ b/docs/api/threading/task/task.md @@ -0,0 +1,88 @@ +# ITask + +**命名空间**: `XCEngine::Threading` + +**类型**: `class` (abstract) + +**头文件**: `XCEngine/Threading/Task.h` + +**描述**: 任务基类抽象接口和任务状态/优先级枚举定义。 + +## 概述 + +`ITask` 是任务系统的核心抽象基类。用户需要继承此类并实现 `Execute()` 方法来定义具体的任务逻辑。任务系统通过引用计数自动管理任务生命周期。 + +## TaskPriority 枚举 + +任务优先级枚举(数值越小优先级越高)。 + +| 值 | 描述 | +|----|------| +| `Critical` | 关键优先级(0) | +| `High` | 高优先级(1) | +| `Normal` | 普通优先级(2) | +| `Low` | 低优先级(3) | +| `Idle` | 空闲优先级(4) | + +## TaskStatus 枚举 + +任务状态枚举。 + +| 值 | 描述 | +|----|------| +| `Pending` | 等待中 | +| `Scheduled` | 已调度 | +| `Running` | 运行中 | +| `Completed` | 已完成 | +| `Failed` | 失败 | +| `Canceled` | 已取消 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `virtual ~ITask()` | 虚析构函数 | +| `ITask()` | 默认构造函数(受保护) | +| `ITask(TaskPriority priority)` | 带优先级的构造函数(受保护) | +| [`Execute`](execute.md) | 任务执行逻辑(纯虚) | +| [`OnComplete`](oncomplete.md) | 任务完成回调(可重写) | +| [`OnCancel`](oncancel.md) | 任务取消回调(可重写) | +| [`GetPriority`](getpriority.md) | 获取优先级 | +| [`GetStatus`](getstatus.md) | 获取状态 | +| [`GetId`](getid.md) | 获取任务 ID | +| [`SetId`](setid.md) | 设置任务 ID | +| [`SetPriority`](setpriority.md) | 设置优先级 | +| [`SetStatus`](setstatus.md) | 设置状态 | +| [`AddRef`](addref.md) | 增加引用计数 | +| [`Release`](release.md) | 减少引用计数(引用归零时自动 delete) | + +## 使用示例 + +```cpp +class MyTask : public ITask { +public: + explicit MyTask(int data) : m_data(data) {} + + void Execute() override { + printf("Task executed with data: %d\n", m_data); + } + + void OnComplete() override { + printf("Task completed\n"); + } + +private: + int m_data; +}; + +auto task = new MyTask(42); +task->SetPriority(TaskPriority::High); +TaskSystem::Get().Submit(std::unique_ptr(task)); +``` + +## 相关文档 + +- [LambdaTask](../lambdatask/lambdatask.md) - Lambda 任务封装 +- [TaskGroup](../task-group/task-group.md) - 任务组 +- [TaskSystem](../task-system/task-system.md) - 任务系统 +- [../threading/threading.md](../threading.md) - 模块总览 diff --git a/docs/api/threading/tasksystemconfig/enabletaskprofiling.md b/docs/api/threading/tasksystemconfig/enabletaskprofiling.md new file mode 100644 index 0000000..d1b5c31 --- /dev/null +++ b/docs/api/threading/tasksystemconfig/enabletaskprofiling.md @@ -0,0 +1,29 @@ +# TaskSystemConfig::enableTaskProfiling + +```cpp +bool enableTaskProfiling = true +``` + +是否启用任务性能分析。启用后系统会记录任务的执行时间、等待时间等统计信息,可用于性能调试。 + +**类型:** `bool` + +**默认值:** `true` + +**当前状态:** 此配置项当前未实际使用,任务系统不会记录性能分析数据。 + +**示例:** + +```cpp +TaskSystemConfig config; +config.workerThreadCount = 4; +config.enableTaskProfiling = true; // 预留配置项 + +#ifdef NDEBUG +config.enableTaskProfiling = false; // 预留配置项 +#endif +``` + +## 相关文档 + +- [TaskSystemConfig 总览](tasksystemconfig.md) - 返回类总览 diff --git a/docs/api/threading/tasksystemconfig/maxtaskqueuesize.md b/docs/api/threading/tasksystemconfig/maxtaskqueuesize.md new file mode 100644 index 0000000..eecebe4 --- /dev/null +++ b/docs/api/threading/tasksystemconfig/maxtaskqueuesize.md @@ -0,0 +1,24 @@ +# TaskSystemConfig::maxTaskQueueSize + +```cpp +uint32_t maxTaskQueueSize = 1024 +``` + +任务队列的最大容量。当队列满时,新提交的任务将阻塞直到有空间。 + +**类型:** `uint32_t` + +**默认值:** `1024` + +**当前状态:** 此配置项当前未实际强制限制,任务队列可以无限增长(受系统内存限制)。 + +**示例:** + +```cpp +TaskSystemConfig config; +config.maxTaskQueueSize = 4096; // 预留配置项(当前未强制限制) +``` + +## 相关文档 + +- [TaskSystemConfig 总览](tasksystemconfig.md) - 返回类总览 diff --git a/docs/api/threading/tasksystemconfig/stealtasks.md b/docs/api/threading/tasksystemconfig/stealtasks.md new file mode 100644 index 0000000..1c46144 --- /dev/null +++ b/docs/api/threading/tasksystemconfig/stealtasks.md @@ -0,0 +1,25 @@ +# TaskSystemConfig::stealTasks + +```cpp +bool stealTasks = true +``` + +是否启用工作窃取。当启用时,空闲的工作线程可以从其他繁忙线程的任务队列中窃取任务,提高整体吞吐率。 + +**类型:** `bool` + +**默认值:** `true` + +**当前状态:** 此配置项当前未实际实现,工作窃取功能不可用。所有工作线程仅从全局任务队列获取任务。 + +**示例:** + +```cpp +TaskSystemConfig config; +config.workerThreadCount = 8; +config.stealTasks = true; // 预留配置项(当前未实现) +``` + +## 相关文档 + +- [TaskSystemConfig 总览](tasksystemconfig.md) - 返回类总览 diff --git a/docs/api/threading/tasksystemconfig/tasksystemconfig.md b/docs/api/threading/tasksystemconfig/tasksystemconfig.md new file mode 100644 index 0000000..142c189 --- /dev/null +++ b/docs/api/threading/tasksystemconfig/tasksystemconfig.md @@ -0,0 +1,36 @@ +# TaskSystemConfig + +**命名空间**: `XCEngine::Threading` + +**类型**: `struct` + +**头文件**: `XCEngine/Threading/TaskSystemConfig.h` + +**描述**: 任务系统配置结构体,用于初始化 TaskSystem 的行为参数。 + +## 结构体成员 + +| 成员 | 类型 | 描述 | 默认值 | +|------|------|------|--------| +| [`workerThreadCount`](workerthreadcount.md) | `uint32_t` | 工作线程数量(0=自动检测 CPU 核心数) | 0 | +| [`enableTaskProfiling`](enabletaskprofiling.md) | `bool` | 启用任务性能分析(当前未使用) | true | +| [`stealTasks`](stealtasks.md) | `bool` | 启用工作窃取(当前未实现) | true | +| [`maxTaskQueueSize`](maxtaskqueuesize.md) | `uint32_t` | 最大任务队列大小(当前未强制限制) | 1024 | +| [`threadStackSize`](threadstacksize.md) | `uint32_t` | 线程栈大小(当前未使用,0=系统默认) | 0 | + +## 使用示例 + +```cpp +TaskSystemConfig config; +config.workerThreadCount = std::thread::hardware_concurrency(); +config.enableTaskProfiling = true; +config.stealTasks = true; +config.maxTaskQueueSize = 2048; + +TaskSystem::Get().Initialize(config); +``` + +## 相关文档 + +- [TaskSystem](../task-system/task-system.md) - 任务系统 +- [../threading/threading.md](../threading.md) - 模块总览 diff --git a/docs/api/threading/tasksystemconfig/threadstacksize.md b/docs/api/threading/tasksystemconfig/threadstacksize.md new file mode 100644 index 0000000..eefcde8 --- /dev/null +++ b/docs/api/threading/tasksystemconfig/threadstacksize.md @@ -0,0 +1,28 @@ +# TaskSystemConfig::threadStackSize + +```cpp +uint32_t threadStackSize = 0 +``` + +工作线程的栈大小(字节)。值为 0 时使用系统默认值。 + +**类型:** `uint32_t` + +**默认值:** `0`(使用系统默认) + +**当前状态:** 此配置项当前未实际使用,工作线程始终使用系统默认栈大小。 + +**示例:** + +```cpp +TaskSystemConfig config; +config.workerThreadCount = 4; +config.threadStackSize = 1024 * 1024; // 预留配置项(当前未实现) + +TaskSystemConfig defaultConfig; +defaultConfig.threadStackSize = 0; // 使用系统默认 +``` + +## 相关文档 + +- [TaskSystemConfig 总览](tasksystemconfig.md) - 返回类总览 diff --git a/docs/api/threading/tasksystemconfig/workerthreadcount.md b/docs/api/threading/tasksystemconfig/workerthreadcount.md new file mode 100644 index 0000000..169d331 --- /dev/null +++ b/docs/api/threading/tasksystemconfig/workerthreadcount.md @@ -0,0 +1,25 @@ +# TaskSystemConfig::workerThreadCount + +```cpp +uint32_t workerThreadCount = 0 +``` + +工作线程数量。当值为 0 时,任务系统自动检测 `std::thread::hardware_concurrency()` 并使用该值。 + +**类型:** `uint32_t` + +**默认值:** `0`(自动检测) + +**示例:** + +```cpp +TaskSystemConfig config; +config.workerThreadCount = 4; // 使用 4 个工作线程 + +TaskSystemConfig autoConfig; +autoConfig.workerThreadCount = 0; // 自动检测(推荐) +``` + +## 相关文档 + +- [TaskSystemConfig 总览](tasksystemconfig.md) - 返回类总览 diff --git a/docs/api/threading/thread/detach.md b/docs/api/threading/thread/detach.md new file mode 100644 index 0000000..4372841 --- /dev/null +++ b/docs/api/threading/thread/detach.md @@ -0,0 +1,38 @@ +# Thread::Detach + +```cpp +void Detach() +``` + +分离线程,使其成为后台线程独立运行。分离后,线程的资源将在其终止时自动释放,调用线程不会被阻塞。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**注意:** +- 分离后的线程无法再被 Join 或进行任何同步操作。 +- 确保分离线程的所有资源访问都是线程安全的,因为主线程可能在分离线程结束前退出。 +- 如果 Thread 对象在分离线程结束前被销毁,行为取决于具体实现。 + +**示例:** + +```cpp +Thread background; +background.Start([]() { + printf("Background task running\n"); + for (int i = 0; i < 3; ++i) { + Thread::Sleep(500); + printf("Background: tick %d\n", i); + } +}, "BackgroundThread"); + +background.Detach(); +printf("Main thread continues immediately\n"); +``` + +## 相关文档 + +- [Thread 总览](thread.md) - 返回类总览 diff --git a/docs/api/threading/thread/getcurrentid.md b/docs/api/threading/thread/getcurrentid.md new file mode 100644 index 0000000..6b5cbc2 --- /dev/null +++ b/docs/api/threading/thread/getcurrentid.md @@ -0,0 +1,30 @@ +# Thread::GetCurrentId + +```cpp +static Id GetCurrentId() +``` + +获取当前执行线程的唯一标识符。这是一个静态方法,可以在任何线程上下文中调用。 + +**参数:** 无 + +**返回:** `Thread::Id` - 当前执行线程的唯一标识符 + +**复杂度:** O(1) + +**示例:** + +```cpp +Thread worker; +worker.Start([]() { + printf("Worker thread id: %llu\n", (unsigned long long)Thread::GetCurrentId()); +}, "WorkerThread"); + +printf("Main thread id: %llu\n", (unsigned long long)Thread::GetCurrentId()); +worker.Join(); +``` + +## 相关文档 + +- [Thread 总览](thread.md) - 返回类总览 +- [GetId](getid.md) - 获取 Thread 对象的 ID diff --git a/docs/api/threading/thread/getid.md b/docs/api/threading/thread/getid.md new file mode 100644 index 0000000..033812a --- /dev/null +++ b/docs/api/threading/thread/getid.md @@ -0,0 +1,30 @@ +# Thread::GetId + +```cpp +Id GetId() const +``` + +获取当前线程对象的唯一标识符。该 ID 在线程启动后有效。 + +**参数:** 无 + +**返回:** `Thread::Id` - 线程的唯一标识符(uint64_t 类型) + +**复杂度:** O(1) + +**注意:** 在调用 Start 之前返回 0。 + +**示例:** + +```cpp +Thread worker; +printf("Before start: id=%llu\n", (unsigned long long)worker.GetId()); +worker.Start([]() {}, "Test"); +printf("After start: id=%llu\n", (unsigned long long)worker.GetId()); +worker.Join(); +``` + +## 相关文档 + +- [Thread 总览](thread.md) - 返回类总览 +- [GetCurrentId](getcurrentid.md) - 获取当前执行线程的 ID diff --git a/docs/api/threading/thread/getname.md b/docs/api/threading/thread/getname.md new file mode 100644 index 0000000..6603fc2 --- /dev/null +++ b/docs/api/threading/thread/getname.md @@ -0,0 +1,28 @@ +# Thread::GetName + +```cpp +const Containers::String& GetName() const +``` + +获取线程的名称。该名称在调用 Start 时设置。 + +**参数:** 无 + +**返回:** `const Containers::String&` - 线程名称的引用 + +**复杂度:** O(1) + +**注意:** 在调用 Start 之前返回空字符串。 + +**示例:** + +```cpp +Thread worker; +worker.Start([]() {}, "ComputeThread"); +printf("Thread name: %s\n", worker.GetName().CStr()); +worker.Join(); +``` + +## 相关文档 + +- [Thread 总览](thread.md) - 返回类总览 diff --git a/docs/api/threading/thread/join.md b/docs/api/threading/thread/join.md new file mode 100644 index 0000000..b0f16c7 --- /dev/null +++ b/docs/api/threading/thread/join.md @@ -0,0 +1,37 @@ +# Thread::Join + +```cpp +void Join() +``` + +等待线程结束并回收其资源。调用线程将被阻塞,直到目标线程完成执行。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(n),n 为目标线程的执行时间 + +**注意:** +- 如果线程已经被分离(Detach)或已经 Join 过,调用此方法将导致未定义行为。 +- 建议在使用完 Thread 对象后始终调用 Join 或 Detach。 + +**示例:** + +```cpp +Thread worker; +worker.Start([]() { + for (int i = 0; i < 5; ++i) { + printf("Working...\n"); + Thread::Sleep(100); + } +}, "WorkerThread"); + +printf("Main thread waiting...\n"); +worker.Join(); +printf("Worker thread finished\n"); +``` + +## 相关文档 + +- [Thread 总览](thread.md) - 返回类总览 diff --git a/docs/api/threading/thread/sleep.md b/docs/api/threading/thread/sleep.md new file mode 100644 index 0000000..9e837dd --- /dev/null +++ b/docs/api/threading/thread/sleep.md @@ -0,0 +1,30 @@ +# Thread::Sleep + +```cpp +static void Sleep(uint32_t milliseconds) +``` + +使当前线程休眠指定的时间。线程在休眠期间不会消耗 CPU 时间。 + +**参数:** +- `milliseconds` - 休眠时间,以毫秒为单位 + +**返回:** 无 + +**复杂度:** 取决于操作系统的调度精度,通常为 O(milliseconds) + +**示例:** + +```cpp +printf("Start\n"); +Thread::Sleep(1000); // 休眠1秒 +printf("After 1 second\n"); + +Thread::Sleep(500); // 再休眠0.5秒 +printf("After 0.5 more seconds\n"); +``` + +## 相关文档 + +- [Thread 总览](thread.md) - 返回类总览 +- [Yield](yield.md) - 让出时间片 diff --git a/docs/api/threading/thread/start.md b/docs/api/threading/thread/start.md new file mode 100644 index 0000000..505d754 --- /dev/null +++ b/docs/api/threading/thread/start.md @@ -0,0 +1,37 @@ +# Thread::Start + +```cpp +template +void Start(Func&& func, const Containers::String& name = "Thread") +``` + +启动线程,执行传入的可调用对象。该方法创建一个新的执行线程,立即开始运行。 + +**参数:** +- `func` - 要在线程中执行的可调用对象(lambda、函数指针、仿函数等) +- `name` - 线程名称,用于调试和日志输出,默认值为 "Thread" + +**返回:** 无 + +**复杂度:** O(1) + +**线程安全:** 该方法不是线程安全的,不应在同一 Thread 对象上并发调用。 + +**示例:** + +```cpp +#include "Threading/Thread.h" + +Thread worker; +worker.Start([]() { + printf("Worker thread running\n"); + Thread::Sleep(100); + printf("Worker thread done\n"); +}, "WorkerThread"); + +worker.Join(); +``` + +## 相关文档 + +- [Thread 总览](thread.md) - 返回类总览 diff --git a/docs/api/threading/thread/thread.md b/docs/api/threading/thread/thread.md new file mode 100644 index 0000000..a6887b9 --- /dev/null +++ b/docs/api/threading/thread/thread.md @@ -0,0 +1,60 @@ +# Thread + +**命名空间**: `XCEngine::Threading` + +**类型**: `class` + +**头文件**: `XCEngine/Threading/Thread.h` + +**描述**: 线程封装类,提供跨平台线程创建和管理功能。 + +## 概述 + +`Thread` 类封装了 `std::thread`,提供统一的线程管理接口,包括启动、加入、分离等操作。 + +## 公共类型 + +| 类型 | 描述 | +|------|------| +| `using Id = uint64_t` | 线程唯一标识符类型 | + +## 公共方法 + +| 方法 | 描述 | +|------|------| +| `Thread()` | 默认构造函数 | +| `~Thread()` | 析构函数 | +| [`Start`](start.md) | 启动线程,执行传入的函数 | +| [`Join`](join.md) | 等待线程结束 | +| [`Detach`](detach.md) | 分离线程,使其独立运行 | +| [`GetId`](getid.md) | 获取线程 ID | +| [`GetName`](getname.md) | 获取线程名称 | +| [`GetCurrentId`](getcurrentid.md) | 获取当前线程 ID | +| [`Sleep`](sleep.md) | 线程休眠指定毫秒数 | +| [`Yield`](yield.md) | 让出当前线程的时间片 | + +## 使用示例 + +```cpp +#include "Threading/Thread.h" + +// 创建并启动线程 +Thread thread; +thread.Start([]() { + printf("Worker thread running\n"); +}, "WorkerThread"); + +// 等待线程结束 +thread.Join(); + +// 使用静态方法 +Thread::Sleep(1000); // 休眠1秒 +Thread::Yield(); // 让出时间片 +auto currentId = Thread::GetCurrentId(); +``` + +## 相关文档 + +- [Mutex](../mutex/mutex.md) - 互斥锁 +- [TaskSystem](../task-system/task-system.md) - 任务调度系统 +- [../threading/threading.md](../threading.md) - 模块总览 diff --git a/docs/api/threading/thread/yield.md b/docs/api/threading/thread/yield.md new file mode 100644 index 0000000..9024b9a --- /dev/null +++ b/docs/api/threading/thread/yield.md @@ -0,0 +1,40 @@ +# Thread::Yield + +```cpp +static void Yield() +``` + +让出当前线程的时间片,允许操作系统调度器将 CPU 时间分配给其他就绪线程。 + +**参数:** 无 + +**返回:** 无 + +**复杂度:** O(1) + +**使用场景:** +- 在自旋等待某个条件时调用,避免浪费 CPU 周期。 +- 在长时间循环中定期让出时间片,提高其他线程的响应性。 + +**示例:** + +```cpp +volatile bool ready = false; + +Thread worker; +worker.Start([]() { + ready = true; +}, "WorkerThread"); + +// 忙等待,但定期让出时间片 +while (!ready) { + Thread::Yield(); +} + +worker.Join(); +``` + +## 相关文档 + +- [Thread 总览](thread.md) - 返回类总览 +- [Sleep](sleep.md) - 线程休眠 diff --git a/docs/api/threading/threading.md b/docs/api/threading/threading.md new file mode 100644 index 0000000..c86e011 --- /dev/null +++ b/docs/api/threading/threading.md @@ -0,0 +1,74 @@ +# Threading 模块概览 + +**命名空间**: `XCEngine::Threading` + +**类型**: `module` + +**描述**: XCEngine 的线程和并发模块,提供多线程编程所需的同步原语和任务系统。 + +## 概述 + +Threading 模块提供了一套完整的多线程编程工具,包括线程封装、同步原语和并行任务系统。 + +## 模块内容 + +### 同步原语 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [Mutex](mutex/mutex.md) | `Mutex.h` | 互斥锁 | +| [SpinLock](spinlock/spinlock.md) | `SpinLock.h` | 自旋锁 | +| [ReadWriteLock](readwritelock/readwritelock.md) | `ReadWriteLock.h` | 读写锁 | + +### 线程 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [Thread](thread/thread.md) | `Thread.h` | 线程封装类 | + +### 任务系统 + +| 组件 | 文件 | 描述 | +|------|------|------| +| [ITask](task/task.md) | `Task.h` | 任务基类 | +| [LambdaTask](lambdatask/lambdatask.md) | `LambdaTask.h` | Lambda 任务封装模板 | +| [TaskGroup](task-group/task-group.md) | `TaskGroup.h` | 任务组 | +| [TaskSystem](task-system/task-system.md) | `TaskSystem.h` | 并行任务调度系统 | +| [TaskSystemConfig](tasksystemconfig/tasksystemconfig.md) | `TaskSystemConfig.h` | 任务系统配置 | + +## 同步原语对比 + +| 原语 | 适用场景 | 特点 | +|------|----------|------| +| `Mutex` | 一般互斥 | 可重入性差,开销适中 | +| `SpinLock` | 短临界区 | 无系统调用,开销低 | +| `ReadWriteLock` | 读多写少 | 读写分离,提高并发 | + +## 任务系统使用示例 + +```cpp +#include "Threading/TaskSystem.h" + +// 初始化任务系统 +TaskSystemConfig config; +config.workerThreadCount = 4; +TaskSystem::Get().Initialize(config); + +// 提交并行任务 +TaskSystem::Get().Submit([]() { + // 执行工作 +}); + +// 使用任务组 +TaskGroup* group = TaskSystem::Get().CreateTaskGroup(); +group->AddTask([]() { /* 任务1 */ }); +group->AddTask([]() { /* 任务2 */ }); +group->Wait(); + +// 销毁任务组 +TaskSystem::Get().DestroyTaskGroup(group); +``` + +## 相关文档 + +- [Memory 模块](../memory/memory.md) - 内存分配器 diff --git a/docs/plan/D3D12后端测试设计.md b/docs/plan/D3D12后端测试设计.md new file mode 100644 index 0000000..a680d3a --- /dev/null +++ b/docs/plan/D3D12后端测试设计.md @@ -0,0 +1,1612 @@ +# D3D12 后端测试设计 + +## 1. 概述 + +本文档描述 XCEngine D3D12 渲染后端的测试框架设计,旨在为 D3D12 各组件提供全面、规范的自动化测试覆盖。 + +### 1.1 测试目标 + +- 验证 D3D12 各组件 API 的正确性 +- 确保组件间的协作正常工作 +- 捕获资源泄漏和内存错误 +- 支持持续集成(CI)自动化测试 + +### 1.2 现有问题 + +当前 `tests/D3D12/main.cpp` 存在以下问题: + +| 问题 | 说明 | +|------|------| +| 非自动化测试 | 截图和对比需手动触发 | +| 缺乏单元测试 | 只有一个 Win32 图形程序,无法使用 Google Test | +| 维护困难 | GT.ppm 是纯黑色图像,对比无实际意义 | +| 容差问题 | 1% 阈值对硬件差异过于敏感 | + +## 2. 测试目录结构 + +### 2.1 资源目录(保留现有 tests/D3D12) + +现有 `tests/D3D12` 目录保留,作为测试资源文件来源: + +``` +tests/D3D12/ +├── Res/ # 测试资源文件(供新测试框架使用) +│ ├── Shader/ +│ │ ├── test_vs.hlsl # 测试用顶点着色器 +│ │ ├── test_ps.hlsl # 测试用像素着色器 +│ │ ├── test_gs.hlsl # 测试用几何着色器 +│ │ ├── test_cs.hlsl # 测试用计算着色器 +│ │ └── test_pattern.hlsl # 图案化测试着色器 +│ ├── Texture/ +│ │ ├── test_256x256.png # 测试用 2D 纹理 +│ │ └── test_cube.dds # 测试用立方体纹理 +│ └── Golden/ +│ ├── clear_color_gt.ppm # 清除颜色基准图像 +│ ├── pattern_checker_gt.ppm # 棋盘格基准图像 +│ └── gradient_gt.ppm # 渐变基准图像 +├── main.cpp # 现有渲染示例(保留) +├── CMakeLists.txt # 现有构建配置(保留) +└── ... # 其他现有文件(保留) +``` + +### 2.2 新测试框架目录 + +在 `tests/D3D12_engine/test/` 下创建新的测试模块: + +``` +tests/D3D12_engine/test/ # 新测试目录 +├── CMakeLists.txt # 测试构建配置 +├── fixtures/ +│ ├── D3D12TestFixture.h # 基础测试夹具 +│ └── D3D12TestFixture.cpp # 夹具实现 +├── test_device.cpp # D3D12Device 测试 +├── test_command_queue.cpp # D3D12CommandQueue 测试 +├── test_command_allocator.cpp # D3D12CommandAllocator 测试 +├── test_command_list.cpp # D3D12CommandList 测试 +├── test_buffer.cpp # D3D12Buffer 测试 +├── test_texture.cpp # D3D12Texture 测试 +├── test_descriptor_heap.cpp # D3D12DescriptorHeap 测试 +├── test_pipeline_state.cpp # D3D12PipelineState 测试 +├── test_root_signature.cpp # D3D12RootSignature 测试 +├── test_fence.cpp # D3D12Fence 测试 +├── test_shader.cpp # D3D12Shader 测试 +├── test_views.cpp # RTV/DSV/SRV/UAV 测试 +└── test_screenshot.cpp # 截图功能测试 +``` +engine/src/RHI/D3D12/ +├── test/ # 新测试目录 +│ ├── CMakeLists.txt # 测试构建配置 +│ ├── fixtures/ +│ │ ├── D3D12TestFixture.h # 基础测试夹具 +│ │ ├── D3D12ResourceFixture.h # 资源测试夹具 +│ │ └── D3D12LeakCheckFixture.h # # 泄漏检测夹具 +│ ├── test_device.cpp # D3D12Device 测试 +│ ├── test_command_queue.cpp # D3D12CommandQueue 测试 +│ ├── test_command_allocator.cpp # D3D12CommandAllocator 测试 +│ ├── test_command_list.cpp # D3D12CommandList 测试 +│ ├── test_buffer.cpp # D3D12Buffer 测试 +│ ├── test_texture.cpp # D3D12Texture 测试 +│ ├── test_descriptor_heap.cpp # D3D12DescriptorHeap 测试 +│ ├── test_pipeline_state.cpp # D3D12PipelineState 测试 +│ ├── test_root_signature.cpp # D3D12RootSignature 测试 +│ ├── test_fence.cpp # D3D12Fence 测试 +│ ├── test_shader.cpp # D3D12Shader 测试 +│ ├── test_views.cpp # RTV/DSV/SRV/UAV 测试 +│ ├── test_types.cpp # 类型转换测试 +│ └── test_screenshot.cpp # 截图功能测试 +│ +├── D3D12Device.cpp # 现有源文件 +├── D3D12CommandQueue.cpp # 现有源文件 +└── ... # 其他现有源文件 +``` + +### 2.3 构建配置说明 + +新的测试框架通过 CMake 添加到引擎构建中: + +```cmake +# engine/CMakeLists.txt 中添加 +if(BUILD_D3D12_TESTS) + enable_testing() + add_subdirectory(src/RHI/D3D12/test) +endif() +``` + +```cmake +# engine/src/RHI/D3D12/test/CMakeLists.txt +cmake_minimum_required(VERSION 3.15) + +project(D3D12EngineTests) + +set(CMAKE_CXX_STANDARD 17) + +# 查找 Google Test +find_package(GTest REQUIRED) + +# 测试源文件 +set(TEST_SOURCES + test_device.cpp + test_command_queue.cpp + test_buffer.cpp + # ... 其他测试文件 +) + +add_executable(d3d12_engine_tests ${TEST_SOURCES}) + +target_link_libraries(d3d12_engine_tests PRIVATE + d3d12 + dxgi + d3dcompiler + XCEngine + GTest::gtest + GTest::gtest_main +) + +# 设置资源目录路径 +target_compile_definitions(d3d12_engine_tests PRIVATE + TEST_RESOURCES_DIR="${CMAKE_SOURCE_DIR}/../../tests/D3D12/Res" +) + +add_test(NAME D3D12EngineTests COMMAND d3d12_engine_tests) + +## 3. 测试夹具设计 + +### 3.1 基础夹具 + +```cpp +// fixtures/D3D12TestFixture.h +#pragma once + +#include +#include +#include + +using namespace Microsoft::WRL; + +class D3D12TestFixture : public ::testing::Test { +protected: + static void SetUpTestSuite() { + // 创建全局 D3D12 设备(所有测试共享) + HRESULT hr = D3D12CreateDevice( + nullptr, // 默认适配器 + D3D_FEATURE_LEVEL_12_0, // 最低支持特性等级 + IID_PPV_ARGS(&mDevice) + ); + ASSERT_TRUE(SUCCEEDED(hr)) << "Failed to create D3D12 device"; + } + + static void TearDownTestSuite() { + mDevice.Reset(); + } + + void SetUp() override { + // 创建命令队列 + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + HRESULT hr = mDevice->CreateCommandQueue( + &queueDesc, + IID_PPV_ARGS(&mCommandQueue) + ); + ASSERT_TRUE(SUCCEEDED(hr)); + + // 创建命令分配器 + hr = mDevice->CreateCommandAllocator( + D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&mCommandAllocator) + ); + ASSERT_TRUE(SUCCEEDED(hr)); + + // 创建命令列表 + hr = mDevice->CreateCommandList( + 0, + D3D12_COMMAND_LIST_TYPE_DIRECT, + mCommandAllocator.Get(), + nullptr, + IID_PPV_ARGS(&mCommandList) + ); + ASSERT_TRUE(SUCCEEDED(hr)); + } + + void TearDown() override { + // 等待所有命令执行完成 + WaitForGPU(); + + mCommandList.Reset(); + mCommandAllocator.Reset(); + mCommandQueue.Reset(); + } + + // 常用辅助方法 + ID3D12Device* GetDevice() { return mDevice.Get(); } + ID3D12CommandQueue* GetCommandQueue() { return mCommandQueue.Get(); } + ID3D12CommandList* GetCommandList() { return mCommandList.Get(); } + + void WaitForGPU() { + ComPtr fence; + UINT64 fenceValue = 1; + + HRESULT hr = mDevice->CreateFence( + 0, + D3D12_FENCE_FLAG_NONE, + IID_PPV_ARGS(&fence) + ); + if (SUCCEEDED(hr)) { + mCommandQueue->Signal(fence.Get(), fenceValue); + HANDLE eventHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr); + fence->SetEventOnCompletion(fenceValue, eventHandle); + WaitForSingleObject(eventHandle, INFINITE); + CloseHandle(eventHandle); + } + } + +private: + static ComPtr mDevice; + ComPtr mCommandQueue; + ComPtr mCommandAllocator; + ComPtr mCommandList; +}; + +// 静态成员定义 +ComPtr D3D12TestFixture::mDevice; +``` + +### 3.2 资源测试夹具 + +```cpp +// fixtures/D3D12ResourceFixture.h +#pragma once + +#include "D3D12TestFixture.h" + +class D3D12ResourceFixture : public D3D12TestFixture { +protected: + void CreateUploadBuffer(size_t size, ID3D12Resource** outResource) { + CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_UPLOAD); + CD3DX12_RESOURCE_DESC bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(size); + + HRESULT hr = GetDevice()->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &bufferDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(outResource) + ); + ASSERT_TRUE(SUCCEEDED(hr)); + } + + void CreateDefaultBuffer(size_t size, ID3D12Resource** outResource) { + CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_DEFAULT); + CD3DX12_RESOURCE_DESC bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(size); + + HRESULT hr = GetDevice()->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &bufferDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(outResource) + ); + ASSERT_TRUE(SUCCEEDED(hr)); + } +}; +``` + +## 4. 测试分类 + +### 4.1 单元测试 + +测试单一 API 的基本功能,不依赖图形硬件渲染结果。 + +```cpp +TEST(D3D12_Buffer, Create_ValidSize_ReturnsSuccess) { + const size_t bufferSize = 1024; + + D3D12Buffer buffer; + bool result = buffer.Initialize(GetDevice(), bufferSize, + D3D12_RESOURCE_STATE_GENERIC_READ, + D3D12_HEAP_TYPE_UPLOAD); + + ASSERT_TRUE(result); + ASSERT_NE(buffer.GetResource(), nullptr); + ASSERT_EQ(buffer.GetResource()->GetDesc().Width, bufferSize); +} + +TEST(D3D12_Buffer, Map_ValidRange_ReturnsValidPointer) { + D3D12Buffer buffer; + buffer.Initialize(GetDevice(), 256, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_HEAP_TYPE_UPLOAD); + + void* mappedData = buffer.Map(0, nullptr); + ASSERT_NE(mappedData, nullptr); + + // 写入测试数据 + memset(mappedData, 0xAB, 256); + buffer.Unmap(0, nullptr); +} + +TEST(D3D12_DescriptorHeap, Create_RTVHeap_ReturnsValidHeap) { + D3D12DescriptorHeap heap; + bool result = heap.Initialize(GetDevice(), D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 4); + + ASSERT_TRUE(result); + ASSERT_NE(heap.GetDescriptorHeap(), nullptr); +} +``` + +### 4.2 集成测试 + +测试多个组件的协作,例如 Buffer 数据上传到 GPU。 + +```cpp +TEST(D3D12_Buffer, UploadToGPU_DataIntegrity) { + const size_t dataSize = sizeof(float) * 4; + float testData[] = { 1.0f, 2.0f, 3.0f, 4.0f }; + + // 创建默认缓冲(GPU 只读) + D3D12Buffer gpuBuffer; + gpuBuffer.Initialize(GetDevice(), dataSize, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_HEAP_TYPE_DEFAULT); + + // 创建上传缓冲(CPU 可写) + D3D12Buffer uploadBuffer; + uploadBuffer.Initialize(GetDevice(), dataSize, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_HEAP_TYPE_UPLOAD); + + // 复制数据到上传缓冲 + void* mappedData = uploadBuffer.Map(0, nullptr); + memcpy(mappedData, testData, dataSize); + uploadBuffer.Unmap(0, nullptr); + + // 通过命令列表复制 + GetCommandList()->CopyBufferRegion( + gpuBuffer.GetResource(), 0, + uploadBuffer.GetResource(), 0, + dataSize + ); + + // 执行并等待 + GetCommandList()->Close(); + ID3D12CommandList* cmdLists[] = { GetCommandList() }; + GetCommandQueue()->ExecuteCommandLists(1, cmdLists); + WaitForGPU(); + + // 验证:使用映射读取返回的数据 + // (需要转换状态到 GENERIC_READ) +} +``` + +### 4.3 渲染结果测试 + +渲染到纹理并验证像素数据,而非渲染到屏幕。 + +#### 4.3.1 测试策略 + +| 方案 | 优点 | 缺点 | +|------|------|------| +| 渲染到 RTT | 无窗口依赖,可 CI | 需要 Mipmap 比较算法 | +| Shader 输出测试值 | 精确验证 | 需要特殊 Shader | +| Golden Image 对比 | 直观 | 维护成本高 | + +#### 4.3.2 推荐方案:渲染特定图案 + +生成一个已知的测试图案(如渐变、棋盘格),渲染后读取像素验证: + +```cpp +TEST(D3D12_RenderTarget, ClearColor_VerifyPixelValue) { + // 创建渲染目标纹理 + const uint32_t width = 64; + const uint32_t height = 64; + + D3D12Texture renderTarget; + renderTarget.InitializeAsRenderTarget( + GetDevice(), width, height, + DXGI_FORMAT_R8G8B8A8_UNORM + ); + + // 创建 RTV + D3D12DescriptorHeap rtvHeap; + rtvHeap.Initialize(GetDevice(), D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1); + + D3D12RenderTargetView rtv; + rtv.InitializeAt( + GetDevice(), + renderTarget.GetResource(), + rtvHeap.GetCPUDescriptorHandleForHeapStart(), + nullptr + ); + + // 清空为特定颜色 + float clearColor[] = { 0.25f, 0.5f, 0.75f, 1.0f }; // R=64, G=128, B=192 + GetCommandList()->ClearRenderTargetView( + rtvHeap.GetCPUDescriptorHandleForHeapStart(), + clearColor, 0, nullptr + ); + + // 转换状态用于读取 + GetCommandList()->TransitionBarrier( + renderTarget.GetResource(), + D3D12_RESOURCE_STATE_RENDER_TARGET, + D3D12_RESOURCE_STATE_COPY_SOURCE + ); + + GetCommandList()->Close(); + ID3D12CommandList* cmdLists[] = { GetCommandList() }; + GetCommandQueue()->ExecuteCommandLists(1, cmdLists); + WaitForGPU(); + + // 读取像素数据 + std::vector pixels(width * height * 4); + ReadBackTexture(GetDevice(), GetCommandQueue(), + renderTarget.GetResource(), pixels.data(), pixels.size()); + + // 验证中心像素 + uint32_t centerIndex = (height / 2 * width + width / 2) * 4; + EXPECT_NEAR(pixels[centerIndex + 0], 64, 2); // R + EXPECT_NEAR(pixels[centerIndex + 1], 128, 2); // G + EXPECT_NEAR(pixels[centerIndex + 2], 192, 2); // B +} +``` + +#### 4.3.3 图案化渲染测试 + +使用纯色 Shader 渲染特定图案: + +```hlsl +// TestPattern.hlsl - 输出棋盘格图案 +float4 PSMain(PSInput input) : SV_Target { + uint2 pixelPos = uint2(input.Position.xy); + bool isWhite = ((pixelPos.x / 8) % 2) == ((pixelPos.y / 8) % 2); + return isWhite ? float4(1,1,1,1) : float4(0,0,0,1); +} +``` + +### 4.4 性能测试 + +使用 Google Benchmark 或简单计时: + +```cpp +TEST(D3D12_Performance, BufferCreation_1000Times) { + const int iterations = 1000; + + auto start = std::chrono::high_resolution_clock::now(); + + for (int i = 0; i < iterations; ++i) { + D3D12Buffer buffer; + buffer.Initialize(GetDevice(), 1024, + D3D12_RESOURCE_STATE_GENERIC_READ, + D3D12_HEAP_TYPE_UPLOAD); + } + + auto end = std::chrono::high_resolution_clock::now(); + auto duration = std::chrono::duration_cast(end - start); + + printf("Created %d buffers in %ld ms\n", iterations, duration.count()); +} +``` + +## 5. 组件测试详情 + +### 5.1 D3D12Device + +```cpp +TEST(D3D12_Device, CheckFeatureSupport_D3D12OK) { + D3D12_FEATURE_DATA_FEATURE_LEVELS featureLevels = {}; + featureLevels.NumFeatureLevels = 1; + featureLevels.pFeatureLevelsRequested = &mFeatureLevel; + + HRESULT hr = GetDevice()->CheckFeatureSupport( + D3D12_FEATURE_FEATURE_LEVELS, + &featureLevels, + sizeof(featureLevels) + ); + + ASSERT_TRUE(SUCCEEDED(hr)); + ASSERT_EQ(featureLevels.MaxSupportedFeatureLevel, D3D_FEATURE_LEVEL_12_0); +} +``` + +### 5.2 D3D12CommandList + +```cpp +TEST(D3D12_CommandList, Reset_AfterClose_Succeeds) { + // 第一次使用 + GetCommandList()->Close(); + + // 重置并再次使用 + HRESULT hr = GetCommandList()->Reset(mCommandAllocator.Get(), nullptr); + ASSERT_TRUE(SUCCEEDED(hr)); +} +``` + +### 5.3 D3D12Fence + +```cpp +TEST(D3D12_Fence, SignalAndWait) { + ComPtr fence; + UINT64 fenceValue = 1; + + HRESULT hr = GetDevice()->CreateFence( + 0, D3D12_FENCE_FLAG_NONE, + IID_PPV_ARGS(&fence) + ); + ASSERT_TRUE(SUCCEEDED(hr)); + + // Signal + GetCommandQueue()->Signal(fence.Get(), fenceValue); + + // 等待 + ASSERT_EQ(fence->GetCompletedValue(), fenceValue); +} +``` + +## 6. 资源泄漏检测 + +### 6.1 使用 D3D12 Debug Layer + +```cpp +#ifdef _DEBUG +class D3D12LeakDetector { +public: + static void BeginFrame() { + if (sDebugDevice) { + sDebugDevice->SetName(L"Leak Detection Frame Start"); + } + } + + static void EndFrame() { + if (sDebugDevice) { + sDebugDevice->SetName(L"Leak Detection Frame End"); + sDebugDevice->ReportLiveDeviceObjects( + D3D12_RDO_FLAGS::D3D12_RDO_FLAG_NONE + ); + } + } + + static void SetDebugDevice(ID3D12DebugDevice* device) { + sDebugDevice = device; + } + +private: + static ID3D12DebugDevice* sDebugDevice; +}; +#endif +``` + +### 6.2 在测试夹具中使用 + +```cpp +class D3D12LeakCheckFixture : public D3D12TestFixture { +protected: + void TearDown() override { + D3D12TestFixture::TearDown(); + +#ifdef _DEBUG + D3D12LeakDetector::EndFrame(); +#endif + } +}; +``` + +## 7. 构建配置 + +### 7.1 CMakeLists.txt 修改 + +```cmake +cmake_minimum_required(VERSION 3.15) + +project(D3D12Tests) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Google Test +include(FetchContent) +FetchContent_Declare( + googletest + GIT_REPOSITORY https://gitee.com/mirrors/googletest.git + GIT_TAG v1.14.0 +) +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) + +enable_testing() + +# 测试源文件 +set(TEST_SOURCES + test_device.cpp + test_command_queue.cpp + test_command_allocator.cpp + test_command_list.cpp + test_buffer.cpp + test_texture.cpp + test_descriptor_heap.cpp + test_pipeline_state.cpp + test_root_signature.cpp + test_fence.cpp + test_shader.cpp + test_views.cpp +) + +add_executable(d3d12_tests ${TEST_SOURCES}) + +target_link_libraries(d3d12_tests PRIVATE + d3d12 + dxgi + d3dcompiler + XCEngine + GTest::gtest + GTest::gtest_main +) + +target_include_directories(d3d12_tests PRIVATE + ${CMAKE_SOURCE_DIR}/engine/include + ${CMAKE_CURRENT_SOURCE_DIR}/fixtures +) + +add_test(NAME D3D12Tests COMMAND d3d12_tests) +``` + +## 8. CI 集成 + +### 8.1 Windows CI 配置示例 + +```yaml +# .github/workflows/d3d12-tests.yml +name: D3D12 Tests + +on: [push, pull_request] + +jobs: + test: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v3 + + - name: Configure + run: cmake -B build -S . -G "Visual Studio 17 2022" + + - name: Build + run: cmake --build build --config Debug + + - name: Run Tests + run: ctest --test-dir build -C Debug --output-on-failure +``` + +## 9. 测试覆盖矩阵 + +| 组件 | 单元测试 | 集成测试 | 渲染测试 | 性能测试 | +|------|:--------:|:--------:|:--------:|:--------:| +| D3D12Device | ✓ | - | - | ✓ | +| D3D12CommandQueue | ✓ | ✓ | - | ✓ | +| D3D12CommandAllocator | ✓ | - | - | - | +| D3D12CommandList | ✓ | ✓ | - | - | +| D3D12Buffer | ✓ | ✓ | - | ✓ | +| D3D12Texture | ✓ | ✓ | ✓ | ✓ | +| D3D12DescriptorHeap | ✓ | - | - | - | +| D3D12PipelineState | ✓ | - | - | - | +| D3D12RootSignature | ✓ | - | - | - | +| D3D12Fence | ✓ | ✓ | - | - | +| D3D12SwapChain | - | - | ✓ | - | +| D3D12Shader | ✓ | - | - | - | +| RTV/DSV/SRV/UAV | ✓ | ✓ | ✓ | - | + +## 10. 组件详细测试用例设计 + +基于对所有 D3D12 组件源代码的深入分析,以下是每个组件的具体可测试 API 点和测试用例设计。 + +### 10.1 D3D12Device 测试 + +**文件**: `test_device.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_WithDebugLayer` | 启用 Debug Layer 后设备创建成功 | +| 初始化 | `Initialize_WithoutDebugLayer` | 不启用 Debug Layer 正常创建 | +| 初始化 | `Initialize_InvalidAdapter` | 无效适配器返回失败 | +| 适配器 | `EnumerateAdapters_ReturnsValidList` | 返回至少一个适配器 | +| 适配器 | `EnumerateAdapters_ContainsRequiredInfo` | 适配器信息包含 Name/VRAM | +| 特性查询 | `CheckFeatureSupport_FeatureLevels` | 查询支持的特性等级 | +| 特性查询 | `CheckFeatureSupport_D3D12Options` | 查询 D3D12 选项支持 | +| 描述符 | `GetDescriptorHandleIncrementSize_RTV` | RTV 描述符增量大小正确 | +| 描述符 | `GetDescriptorHandleIncrementSize_DSV` | DSV 描述符增量大小正确 | +| 描述符 | `GetDescriptorHandleIncrementSize_CBV_SRV_UAV` | SRV/CBV/UAV 增量正确 | +| 工厂方法 | `CreateCommandQueue_ReturnsValidObject` | 创建命令队列成功 | +| 工厂方法 | `CreateBuffer_ReturnsValidObject` | 创建 Buffer 成功 | +| 工厂方法 | `CreateTexture_ReturnsValidObject` | 创建 Texture 成功 | +| 工厂方法 | `CreateDescriptorHeap_ReturnsValidObject` | 创建描述符堆成功 | +| 工厂方法 | `CreatePipelineState_ReturnsValidObject` | 创建 PSO 成功 | +| 工厂方法 | `CreateRootSignature_ReturnsValidObject` | 创建根签名成功 | +| 设备状态 | `SetDeviceRemoved_MarksAsRemoved` | 设备移除标记正确 | +| 设备状态 | `IsDeviceRemoved_ReturnsCorrectState` | 移除状态查询正确 | + +**测试代码示例**: + +```cpp +TEST(D3D12Device, Initialize_WithDebugLayer_Success) { + D3D12Device device; + bool result = device.Initialize(true); + + ASSERT_TRUE(result); + ASSERT_NE(device.GetDevice(), nullptr); + + // 验证 Debug Layer 已启用 + ComPtr debugDevice; + if (SUCCEEDED(device.GetDevice()->QueryInterface(IID_PPV_ARGS(&debugDevice)))) { + ASSERT_NE(debugDevice.Get(), nullptr); + } + + device.Shutdown(); +} + +TEST(D3D12Device, EnumerateAdapters_ContainsValidInfo) { + D3D12Device device; + device.Initialize(); + + auto adapters = device.EnumerateAdapters(); + + ASSERT_FALSE(adapters.empty()); + for (const auto& info : adapters) { + EXPECT_FALSE(info.name.empty()); + EXPECT_GE(info.vram, 0); + } +} + +TEST(D3D12Device, CreateBuffer_FactoryMethod) { + D3D12Device device; + device.Initialize(); + + BufferDesc desc; + desc.size = 1024; + desc.usage = ResourceUsage::VertexBuffer; + + auto* buffer = device.CreateBuffer(desc); + ASSERT_NE(buffer, nullptr); + ASSERT_EQ(buffer->GetSize(), 1024); +} +``` + +--- + +### 10.2 D3D12CommandQueue 测试 + +**文件**: `test_command_queue.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_DirectQueue` | Direct 类型队列创建成功 | +| 初始化 | `Initialize_ComputeQueue` | Compute 类型队列创建成功 | +| 初始化 | `Initialize_CopyQueue` | Copy 类型队列创建成功 | +| 同步 | `Signal_SetsFenceValue` | Signal 设置围栏值 | +| 同步 | `Wait_BlocksUntilSignal` | Wait 阻塞直到信号 | +| 同步 | `SignalAndWait_Completes` | 信号后等待完成 | +| 同步 | `WaitForIdle_BlocksAllWork` | 等待空闲完成所有工作 | +| 查询 | `GetTimestampFrequency_ReturnsValid` | 时间戳频率有效 | +| 查询 | `GetType_ReturnsCorrect` | 队列类型正确 | + +**测试代码示例**: + +```cpp +TEST(D3D12CommandQueue, Signal_SetsFenceValue) { + D3D12Fence fence; + fence.Initialize(GetDevice(), 0); + + GetCommandQueue()->Signal(fence.GetFence(), 1); + + // 需要等待完成 + fence.Wait(1); + EXPECT_EQ(fence.GetCompletedValue(), 1); +} + +TEST(D3D12CommandQueue, WaitForIdle_BlocksAllWork) { + // 先执行一些命令 + D3D12Buffer buffer; + buffer.Initialize(GetDevice(), 256, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_HEAP_TYPE_UPLOAD); + + GetCommandList()->Close(); + ID3D12CommandList* lists[] = { GetCommandList() }; + GetCommandQueue()->ExecuteCommandLists(1, lists); + + // 等待空闲 + GetCommandQueue()->WaitForIdle(); + + // 验证完成 + EXPECT_TRUE(true); // 如果没崩溃说明成功 +} +``` + +--- + +### 10.3 D3D12CommandAllocator 测试 + +**文件**: `test_command_allocator.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_DirectType` | Direct 类型创建成功 | +| 初始化 | `Initialize_ComputeType` | Compute 类型创建成功 | +| 初始化 | `Initialize_CopyType` | Copy 类型创建成功 | +| 重置 | `Reset_AfterCommandList` | 命令列表执行后重置成功 | +| 状态 | `IsReady_BeforeAndAfterReset` | 重置前后状态正确 | + +**测试代码示例**: + +```cpp +TEST(D3D12CommandAllocator, Reset_AfterCommandListExecution) { + D3D12CommandAllocator allocator; + allocator.Initialize(GetDevice(), CommandQueueType::Direct); + + // 执行命令列表 + GetCommandList()->Close(); + ID3D12CommandList* lists[] = { GetCommandList() }; + GetCommandQueue()->ExecuteCommandLists(1, lists); + WaitForGPU(); + + // 重置分配器 + allocator.Reset(); + + // 验证可以创建新的命令列表 + ComPtr newList; + HRESULT hr = GetDevice()->CreateCommandList( + 0, D3D12_COMMAND_LIST_TYPE_DIRECT, + allocator.GetCommandAllocator(), nullptr, + IID_PPV_ARGS(&newList) + ); + ASSERT_TRUE(SUCCEEDED(hr)); +} +``` + +--- + +### 10.4 D3D12CommandList 测试 + +**文件**: `test_command_list.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 生命周期 | `Initialize_CreatesValidList` | 创建成功 | +| 生命周期 | `Reset_ReusesAllocator` | 重置成功 | +| 生命周期 | `Close_BeforeExecute` | 关闭后可以执行 | +| 资源屏障 | `TransitionBarrier_ValidStates` | 状态转换正确 | +| 资源屏障 | `UAVBarrier_CreatesBarrier` | UAV 屏障创建 | +| 资源屏障 | `AliasBarrier_CreatesBarrier` | 别名屏障创建 | +| 状态设置 | `SetViewport_SetsCorrectValues` | 视口设置正确 | +| 状态设置 | `SetScissorRect_SetsCorrectValues` | 裁剪矩形设置正确 | +| 状态设置 | `SetPrimitiveTopology_TriangleList` | 图元拓扑设置 | +| 绘制 | `Draw_ValidParameters` | 绘制调用参数正确 | +| 绘制 | `DrawIndexed_ValidParameters` | 索引绘制调用正确 | +| 清除 | `ClearRenderTargetView_ClearsColor` | 清除颜色正确 | +| 清除 | `ClearDepthStencilView_ClearsDepth` | 清除深度模板正确 | +| 复制 | `CopyBuffer_TransfersData` | Buffer 复制正确 | +| 复制 | `CopyTexture_TransfersData` | Texture 复制正确 | +| 查询 | `BeginQuery_StartsQuery` | 查询开始 | +| 查询 | `EndQuery_EndsQuery` | 查询结束 | +| 查询 | `ResolveQueryData_CopiesResults` | 查询数据解析 | + +**测试代码示例**: + +```cpp +TEST(D3D12CommandList, TransitionBarrier_ValidStates) { + D3D12Buffer buffer; + buffer.Initialize(GetDevice(), 1024, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_HEAP_TYPE_UPLOAD); + + // 从通用读取状态转换到渲染目标状态 + GetCommandList()->TransitionBarrier( + buffer.GetResource(), + ResourceStates::GenericRead, + ResourceStates::RenderTarget + ); + + GetCommandList()->Close(); + + // 执行命令 + ID3D12CommandList* lists[] = { GetCommandList() }; + GetCommandQueue()->ExecuteCommandLists(1, lists); + WaitForGPU(); + + // 成功执行无崩溃 + SUCCEED(); +} + +TEST(D3D12CommandList, ClearRenderTargetView_VerifyColor) { + // 创建渲染目标 + D3D12Texture rt; + D3D12DescriptorHeap heap; + heap.Initialize(GetDevice(), DescriptorHeapType::RTV, 1); + + // 简化测试:创建 RTV + // ... + + float clearColor[] = { 0.25f, 0.5f, 0.75f, 1.0f }; + GetCommandList()->ClearRenderTargetView( + heap.GetCPUDescriptorHandleForHeapStart(), + clearColor, 0, nullptr + ); + + GetCommandList()->Close(); + ID3D12CommandList* lists[] = { GetCommandList() }; + GetCommandQueue()->ExecuteCommandLists(1, lists); + WaitForGPU(); + + SUCCEED(); +} +``` + +--- + +### 10.5 D3D12Buffer 测试 + +**文件**: `test_buffer.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_DefaultHeap` | 默认堆创建成功 | +| 初始化 | `Initialize_UploadHeap` | 上传堆创建成功 | +| 初始化 | `Initialize_ReadbackHeap` | 回读堆创建成功 | +| 初始化 | `InitializeFromExisting_WrapsResource` | 包装现有资源 | +| 初始化 | `InitializeWithData_CopiesData` | 带数据初始化复制数据 | +| 数据操作 | `Map_ReturnsValidPointer` | Map 返回有效指针 | +| 数据操作 | `Unmap_ReleasesPointer` | Unmap 释放指针 | +| 数据操作 | `UpdateData_ModifiesContent` | 更新数据正确 | +| 属性 | `GetGPUVirtualAddress_ReturnsValid` | GPU 虚拟地址有效 | +| 属性 | `GetDesc_ReturnsCorrectDesc` | 描述符正确 | +| 属性 | `GetSize_ReturnsCorrectSize` | 大小正确 | +| 状态 | `GetState_ReturnsCurrent` | 状态查询正确 | +| 状态 | `SetState_ChangesState` | 状态设置正确 | + +**测试代码示例**: + +```cpp +TEST(D3D12Buffer, Initialize_UploadHeap_MapsSuccessfully) { + D3D12Buffer buffer; + bool result = buffer.Initialize(GetDevice(), 1024, + D3D12_RESOURCE_STATE_GENERIC_READ, + D3D12_HEAP_TYPE_UPLOAD); + + ASSERT_TRUE(result); + + // Map 操作 + void* data = buffer.Map(0, nullptr); + ASSERT_NE(data, nullptr); + + // 写入测试数据 + memset(data, 0xAB, 1024); + buffer.Unmap(0, nullptr); + + // 再次 Map 验证 + data = buffer.Map(0, nullptr); + ASSERT_NE(data, nullptr); + + // 验证数据 + uint8_t* byteData = static_cast(data); + for (int i = 0; i < 1024; ++i) { + EXPECT_EQ(byteData[i], 0xAB); + } + + buffer.Unmap(0, nullptr); +} + +TEST(D3D12Buffer, InitializeWithData_DataIntegrity) { + const size_t dataSize = 256; + std::vector testData(dataSize); + for (size_t i = 0; i < dataSize; ++i) { + testData[i] = static_cast(i & 0xFF); + } + + D3D12Buffer buffer; + bool result = buffer.InitializeWithData( + GetDevice(), GetCommandList(), + testData.data(), dataSize, + ResourceStates::VertexAndConstantBuffer + ); + + ASSERT_TRUE(result); + + WaitForGPU(); + + // 验证 GPU 地址有效 + EXPECT_NE(buffer.GetGPUVirtualAddress(), 0); +} +``` + +--- + +### 10.6 D3D12Texture 测试 + +**文件**: `test_texture.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_2DTexture` | 2D 纹理创建成功 | +| 初始化 | `Initialize_3DTexture` | 3D 纹理创建成功 | +| 初始化 | `Initialize_CubeTexture` | 立方体纹理创建成功 | +| 初始化 | `Initialize_WithMipLevels` | 多 Mip 级别创建 | +| 初始化 | `Initialize_DepthStencil` | 深度模板纹理创建 | +| 初始化 | `InitializeFromData_CopiesPixels` | 带像素数据初始化 | +| 属性 | `GetWidth_ReturnsCorrect` | 宽度正确 | +| 属性 | `GetHeight_ReturnsCorrect` | 高度正确 | +| 属性 | `GetDepth_ReturnsCorrect` | 深度正确 | +| 属性 | `GetMipLevels_ReturnsCorrect` | Mip 级别数正确 | +| 属性 | `GetFormat_ReturnsCorrect` | 格式正确 | +| 状态 | `GetState_ReturnsCurrent` | 状态查询正确 | +| 状态 | `SetState_ChangesState` | 状态设置正确 | + +**测试代码示例**: + +```cpp +TEST(D3D12Texture, Initialize_2DTexture_CorrectDimensions) { + D3D12Texture texture; + + D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Tex2D( + DXGI_FORMAT_R8G8B8A8_UNORM, 512, 512 + ); + + bool result = texture.Initialize(GetDevice(), desc, D3D12_RESOURCE_STATE_COMMON); + + ASSERT_TRUE(result); + EXPECT_EQ(texture.GetWidth(), 512); + EXPECT_EQ(texture.GetHeight(), 512); + EXPECT_EQ(texture.GetDepth(), 1); + EXPECT_EQ(texture.GetMipLevels(), 1); +} + +TEST(D3D12Texture, InitializeDepthStencil_CorrectFormat) { + D3D12Texture depthStencil; + bool result = depthStencil.InitializeDepthStencil( + GetDevice(), 1280, 720, DXGI_FORMAT_D24_UNORM_S8_UINT + ); + + ASSERT_TRUE(result); + EXPECT_EQ(depthStencil.GetFormat(), Format::D24_UNorm_S8_UInt); +} +``` + +--- + +### 10.7 D3D12DescriptorHeap 测试 + +**文件**: `test_descriptor_heap.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_RTVHeap` | RTV 堆创建成功 | +| 初始化 | `Initialize_DSVHeap` | DSV 堆创建成功 | +| 初始化 | `Initialize_CBV_SRV_UAVHeap` | CBV/SRV/UAV 堆创建 | +| 初始化 | `Initialize_SamplerHeap` | 采样器堆创建 | +| 初始化 | `Initialize_ShaderVisible` | 着色器可见堆创建 | +| 句柄 | `GetCPUDescriptorHandle_ValidIndex` | CPU 句柄正确 | +| 句柄 | `GetGPUDescriptorHandle_ValidIndex` | GPU 句柄正确 | +| 句柄 | `GetCPUDescriptorHandleForHeapStart` | 起始句柄正确 | +| 属性 | `GetDescriptorCount_ReturnsCorrect` | 描述符数量正确 | +| 属性 | `GetDescriptorSize_ReturnsCorrect` | 描述符大小正确 | +| 属性 | `GetType_ReturnsCorrect` | 类型正确 | + +**测试代码示例**: + +```cpp +TEST(D3D12DescriptorHeap, Initialize_SRVHeapWithShaderVisible) { + D3D12DescriptorHeap heap; + bool result = heap.Initialize( + GetDevice(), + DescriptorHeapType::CBV_SRV_UAV, + 16, + true // shader visible + ); + + ASSERT_TRUE(result); + EXPECT_EQ(heap.GetDescriptorCount(), 16); + EXPECT_EQ(heap.GetType(), DescriptorHeapType::CBV_SRV_UAV); + + // 验证 GPU 句柄可用 + auto gpuHandle = heap.GetGPUDescriptorHandle(0); + EXPECT_NE(gpuHandle.ptr, 0); +} + +TEST(D3D12DescriptorHeap, GetDescriptorSize_MatchesIncrement) { + D3D12DescriptorHeap heap; + heap.Initialize(GetDevice(), DescriptorHeapType::RTV, 4); + + UINT incrementSize = GetDevice()->GetDescriptorHandleIncrementSize( + D3D12_DESCRIPTOR_HEAP_TYPE_RTV + ); + + EXPECT_EQ(heap.GetDescriptorSize(), incrementSize); +} +``` + +--- + +### 10.8 D3D12Shader 测试 + +**文件**: `test_shader.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 编译 | `CompileFromFile_VertexShader` | VS 编译成功 | +| 编译 | `CompileFromFile_PixelShader` | PS 编译成功 | +| 编译 | `CompileFromFile_GeometryShader` | GS 编译成功 | +| 编译 | `CompileFromFile_ComputeShader` | CS 编译成功 | +| 编译 | `CompileFromFile_InvalidFile` | 无效文件返回失败 | +| 编译 | `CompileFromFile_InvalidEntry` | 无效入口点返回失败 | +| 编译 | `CompileFromFile_InvalidTarget` | 无效目标返回失败 | +| 字节码 | `GetD3D12Bytecode_ReturnsValid` | 字节码有效 | +| 字节码 | `GetBytecodeSize_ReturnsNonZero` | 字节码大小非零 | +| 属性 | `GetType_ReturnsCorrect` | 类型正确 | + +**测试代码示例**: + +```cpp +TEST(D3D12Shader, CompileFromFile_VertexShader_Success) { + D3D12Shader shader; + bool result = shader.CompileFromFile( + L"Res/Shader/test_vs.hlsl", + "main", + "vs_5_1" + ); + + ASSERT_TRUE(result); + EXPECT_EQ(shader.GetType(), ShaderType::Vertex); + EXPECT_GT(shader.GetBytecodeSize(), 0); +} + +TEST(D3D12Shader, CompileFromFile_InvalidFile_ReturnsFalse) { + D3D12Shader shader; + bool result = shader.CompileFromFile( + L"NonExistent.hlsl", + "main", + "vs_5_1" + ); + + EXPECT_FALSE(result); +} +``` + +--- + +### 10.9 D3D12PipelineState 测试 + +**文件**: `test_pipeline_state.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_GraphicsPipeline` | 图形管线创建成功 | +| 初始化 | `Initialize_ComputePipeline` | 计算管线创建成功 | +| 工厂方法 | `CreateDesc_ValidParameters` | 描述符创建正确 | +| 工厂方法 | `CreateInputElement_ValidParams` | 输入元素创建正确 | +| 属性 | `GetPipelineState_ReturnsValid` | PSO 对象有效 | +| 属性 | `GetType_ReturnsCorrect` | 类型正确 | + +**测试代码示例**: + +```cpp +TEST(D3D12PipelineState, Initialize_GraphicsPipeline_Success) { + // 创建根签名 + D3D12RootSignature rootSig; + D3D12_ROOT_PARAMETER params[1] = {}; + params[0] = D3D12RootSignature::CreateCBV(0); + D3D12_ROOT_SIGNATURE_DESC rsDesc = D3D12RootSignature::CreateDesc(params, 1); + rootSig.Initialize(GetDevice(), rsDesc); + + // 编译简单 Shader + D3D12Shader vs, ps; + vs.CompileFromFile(L"Res/Shader/test_vs.hlsl", "main", "vs_5_1"); + ps.CompileFromFile(L"Res/Shader/test_ps.hlsl", "main", "ps_5_1"); + + // 创建 PSO + D3D12PipelineState pso; + auto desc = D3D12PipelineState::CreateDesc( + rootSig.GetRootSignature(), + vs.GetD3D12Bytecode(), + ps.GetD3D12Bytecode(), + {}, // GS + 0, nullptr // input elements + ); + + bool result = pso.Initialize(GetDevice(), desc); + ASSERT_TRUE(result); + ASSERT_NE(pso.GetPipelineState(), nullptr); +} +``` + +--- + +### 10.10 D3D12RootSignature 测试 + +**文件**: `test_root_signature.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_ValidDesc` | 有效描述符创建成功 | +| 初始化 | `Initialize_WithCBV` | 带 CBV 参数创建 | +| 初始化 | `Initialize_WithSRV` | 带 SRV 参数创建 | +| 初始化 | `Initialize_WithDescriptorTable` | 带描述符表创建 | +| 初始化 | `Initialize_WithStaticSampler` | 带静态采样器创建 | +| 工厂方法 | `CreateCBV_ReturnsValid` | CBV 创建正确 | +| 工厂方法 | `CreateSRV_ReturnsValid` | SRV 创建正确 | +| 工厂方法 | `CreateUAV_ReturnsValid` | UAV 创建正确 | +| 工厂方法 | `Create32BitConstants_ReturnsValid` | 常量创建正确 | +| 工厂方法 | `CreateDescriptorTable_ReturnsValid` | 描述符表创建正确 | +| 工厂方法 | `CreateSamplerDesc_ReturnsValid` | 采样器描述创建正确 | +| 属性 | `GetRootSignature_ReturnsValid` | 根签名对象有效 | +| 属性 | `GetParameterCount_ReturnsCorrect` | 参数数量正确 | + +**测试代码示例**: + +```cpp +TEST(D3D12RootSignature, Initialize_WithDescriptorTable) { + D3D12_DESCRIPTOR_RANGE ranges[1]; + ranges[0] = D3D12RootSignature::CreateDescriptorRange( + D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 0, 1 + ); + + D3D12_ROOT_PARAMETER params[1]; + params[0] = D3D12RootSignature::CreateDescriptorTable(1, ranges); + + D3D12_ROOT_SIGNATURE_DESC desc = D3D12RootSignature::CreateDesc(params, 1); + + D3D12RootSignature rootSig; + bool result = rootSig.Initialize(GetDevice(), desc); + + ASSERT_TRUE(result); + ASSERT_NE(rootSig.GetRootSignature(), nullptr); + EXPECT_EQ(rootSig.GetParameterCount(), 1); +} + +TEST(D3D12RootSignature, CreateSamplerDesc_AllParameters) { + auto desc = D3D12RootSignature::CreateSamplerDesc( + FilterMode::Linear, + TextureAddressMode::Clamp, + 16.0f + ); + + EXPECT_EQ(desc.Filter, D3D12_FILTER_MIN_MAG_MIP_LINEAR); + EXPECT_EQ(desc.AddressU, D3D12_TEXTURE_ADDRESS_MODE_CLAMP); + EXPECT_EQ(desc.MaxLOD, 16.0f); +} +``` + +--- + +### 10.11 视图测试 (RTV/DSV/SRV/UAV/CBV) + +**文件**: `test_views.cpp` + +**可测试 API 点**: + +| 组件 | 测试用例 | 验证内容 | +|------|----------|----------| +| RTV | `Initialize_2DTexture` | 2D 纹理 RTV 创建 | +| RTV | `CreateDesc_ValidFormat` | RTV 描述符创建 | +| DSV | `Initialize_DepthTexture` | 深度纹理 DSV 创建 | +| DSV | `CreateDesc_ValidFormat` | DSV 描述符创建 | +| SRV | `Initialize_Texture` | 纹理 SRV 创建 | +| SRV | `CreateDesc_WithMipLevels` | 带 Mip 级别 SRV | +| UAV | `Initialize_Buffer` | Buffer UAV 创建 | +| UAV | `Initialize_Texture` | Texture UAV 创建 | +| CBV | `Initialize_Buffer` | Buffer CBV 创建 | +| CBV | `Initialize_AutoDesc` | 自动描述符 CBV | + +**测试代码示例**: + +```cpp +TEST(D3D12RenderTargetView, Initialize_2DTexture_Success) { + D3D12Texture texture; + D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Tex2D( + DXGI_FORMAT_R8G8B8A8_UNORM, 256, 256 + ); + texture.Initialize(GetDevice(), desc); + + D3D12DescriptorHeap heap; + heap.Initialize(GetDevice(), DescriptorHeapType::RTV, 1); + + D3D12RenderTargetView rtv; + rtv.Initialize( + GetDevice(), + texture.GetResource(), + nullptr + ); + + EXPECT_NE(rtv.GetCPUDescriptorHandle().ptr, 0); +} + +TEST(D3D12DepthStencilView, Initialize_DepthTexture_Success) { + D3D12Texture depthTexture; + depthTexture.InitializeDepthStencil( + GetDevice(), 1280, 720, DXGI_FORMAT_D24_UNORM_S8_UINT + ); + + D3D12DescriptorHeap heap; + heap.Initialize(GetDevice(), DescriptorHeapType::DSV, 1); + + D3D12DepthStencilView dsv; + auto desc = D3D12DepthStencilView::CreateDesc(Format::D24_UNorm_S8_UInt); + dsv.Initialize( + GetDevice(), + depthTexture.GetResource(), + &desc + ); + + EXPECT_NE(dsv.GetCPUDescriptorHandle().ptr, 0); +} +``` + +--- + +### 10.12 D3D12Fence 测试 + +**文件**: `test_fence.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_DefaultValue` | 默认初始值创建 | +| 初始化 | `Initialize_CustomValue` | 自定义初始值创建 | +| 同步 | `Signal_SetsValue` | Signal 设置值 | +| 同步 | `Wait_BlocksUntilSignaled` | Wait 阻塞等待 | +| 同步 | `GetCompletedValue_ReturnsCurrent` | 完成值查询 | +| 事件 | `GetEventHandle_ReturnsValid` | 事件句柄有效 | + +**测试代码示例**: + +```cpp +TEST(D3D12Fence, Signal_UpdatesCompletedValue) { + D3D12Fence fence; + fence.Initialize(GetDevice(), 0); + + GetCommandQueue()->Signal(fence.GetFence(), 5); + + fence.Wait(5); + + EXPECT_EQ(fence.GetCompletedValue(), 5); +} +``` + +--- + +### 10.13 类型转换测试 + +**文件**: `test_types.cpp` + +**可测试 API 点**: + +| 组件 | 测试用例 | 验证内容 | +|------|----------|----------| +| D3D12Enum | `ToD3D12_FillMode_All` | 所有填充模式转换 | +| D3D12Enum | `ToD3D12_CullMode_All` | 所有剔除模式转换 | +| D3D12Enum | `ToD3D12_ComparisonFunc_All` | 所有比较函数转换 | +| D3D12Enum | `ToD3D12_BlendOp_All` | 所有混合操作转换 | +| D3D12Enum | `ToD3D12_Format_Common` | 常用格式转换 | +| D3D12Enum | `ToD3D12_ResourceStates_All` | 所有资源状态转换 | +| D3D12Types | `ToD3D12_Viewport_Correct` | Viewport 转换正确 | +| D3D12Types | `ToD3D12_TextureDesc_Correct` | 纹理描述符转换正确 | +| D3D12Types | `ToD3D12_BufferDesc_Correct` | Buffer 描述符转换正确 | +| D3D12Common | `CheckFormatSupport_CommonFormats` | 常用格式支持检查 | +| D3D12Common | `IsRenderTargetFormatSupported_Common` | 渲染目标格式支持 | + +**测试代码示例**: + +```cpp +TEST(D3D12Enum, ToD3D12_FillMode_All) { + EXPECT_EQ(ToD3D12(FillMode::Wireframe), D3D12_FILL_MODE_WIREFRAME); + EXPECT_EQ(ToD3D12(FillMode::Solid), D3D12_FILL_MODE_SOLID); +} + +TEST(D3D12Enum, ToD3D12_ResourceStates_All) { + EXPECT_EQ(ToD3D12(ResourceStates::Common), D3D12_RESOURCE_STATE_COMMON); + EXPECT_EQ(ToD3D12(ResourceStates::RenderTarget), D3D12_RESOURCE_STATE_RENDER_TARGET); + EXPECT_EQ(ToD3D12(ResourceStates::DepthWrite), D3D12_RESOURCE_STATE_DEPTH_WRITE); + EXPECT_EQ(ToD3D12(ResourceStates::VertexAndConstantBuffer), D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER); + EXPECT_EQ(ToD3D12(ResourceStates::IndexBuffer), D3D12_RESOURCE_STATE_INDEX_BUFFER); +} +``` + +--- + +## 11. 测试实现优先级 + +根据组件的依赖关系和重要性,建议按以下顺序实现测试: + +### Phase 1: 核心基础设施 (高优先级) + +1. **D3D12Device** - 所有其他组件依赖 +2. **D3D12CommandQueue** - 命令执行基础 +3. **D3D12CommandAllocator** - 命令分配基础 +4. **D3D12Fence** - 同步基础 + +### Phase 2: 资源管理 (中优先级) + +5. **D3D12Buffer** - 最常用的资源 +6. **D3D12Texture** - 纹理资源 +7. **D3D12DescriptorHeap** - 描述符管理 + +### Phase 3: 渲染管线 (中优先级) + +8. **D3D12Shader** - 着色器编译 +9. **D3D12RootSignature** - 根签名 +10. **D3D12PipelineState** - 管线状态 + +### Phase 4: 视图和命令 (低优先级) + +11. **RTV/DSV/SRV/UAV/CBV** - 各种视图 +12. **D3D12CommandList** - 命令录制 + +### Phase 5: 高级功能 (最低优先级) + +13. **D3D12SwapChain** - 需要窗口 +14. **D3D12Screenshot** - 截图功能 +15. **类型转换** - 辅助函数测试 + +--- + +## 12. 测试数据文件 + +测试所需资源文件从 `tests/D3D12/Res/` 目录获取: + +``` +tests/D3D12/Res/ +├── Shader/ +│ ├── test_vs.hlsl # 测试用顶点着色器 +│ ├── test_ps.hlsl # 测试用像素着色器 +│ ├── test_gs.hlsl # 测试用几何着色器 +│ ├── test_cs.hlsl # 测试用计算着色器 +│ └── test_pattern.hlsl # 图案化测试着色器 +├── Texture/ +│ ├── test_256x256.png # 测试用 2D 纹理 +│ └── test_cube.dds # 测试用立方体纹理 +└── Golden/ + ├── clear_color_gt.ppm # 清除颜色基准图像 + ├── pattern_checker_gt.ppm # 棋盘格基准图像 + └── gradient_gt.ppm # 渐变基准图像 +``` + +### 12.1 在测试中引用资源 + +```cpp +// 通过编译定义获取资源路径 +#ifndef TEST_RESOURCES_DIR +#define TEST_RESOURCES_DIR "tests/D3D12/Res" +#endif + +TEST(D3D12Shader, CompileFromFile_VertexShader) { + D3D12Shader shader; + + // 构建资源路径 + std::wstring shaderPath = std::wstring(TEST_RESOURCES_DIR) + L"/Shader/test_vs.hlsl"; + + bool result = shader.CompileFromFile(shaderPath.c_str(), "main", "vs_5_1"); + + ASSERT_TRUE(result); +} + +--- + +## 13. 构建计划与执行流程 + +本文档描述的测试框架将按照以下计划逐步构建,每完成一个步骤即进行测试、提交并推送。 + +### 13.1 构建计划总览 + +| 步骤 | 文件 | 内容 | 验证方式 | +|------|------|------|----------| +| **步骤 1: 基础设施搭建** | +| 1.1 | `engine/src/RHI/D3D12/test/CMakeLists.txt` | 测试构建配置 | CMake 配置检查 | +| 1.2 | `engine/src/RHI/D3D12/test/fixtures/D3D12TestFixture.h` | 基础测试夹具 | 编译通过 | +| **步骤 2: 核心组件测试** | +| 2.1 | `test_device.cpp` | D3D12Device 初始化、适配器枚举、特性查询 | 运行测试 | +| 2.2 | `test_fence.cpp` | D3D12Fence 同步、Signal/Wait | 运行测试 | +| **步骤 3: 命令系统测试** | +| 3.1 | `test_command_queue.cpp` | 队列创建、执行命令、同步 | 运行测试 | +| 3.2 | `test_command_allocator.cpp` | 分配器创建、重置 | 运行测试 | +| 3.3 | `test_command_list.cpp` | 命令录制、资源屏障、绘制 | 运行测试 | +| **步骤 4: 资源测试** | +| 4.1 | `test_buffer.cpp` | Buffer 创建、Map/Unmap、数据上传 | 运行测试 | +| 4.2 | `test_texture.cpp` | 纹理创建、深度模板 | 运行测试 | +| 4.3 | `test_descriptor_heap.cpp` | 描述符堆创建、句柄获取 | 运行测试 | +| **步骤 5: 渲染管线测试** | +| 5.1 | `test_shader.cpp` | Shader 编译 | 运行测试 | +| 5.2 | `test_root_signature.cpp` | 根签名创建、参数 | 运行测试 | +| 5.3 | `test_pipeline_state.cpp` | PSO 创建 | 运行测试 | +| **步骤 6: 视图测试** | +| 6.1 | `test_views.cpp` | RTV/DSV/SRV/UAV/CBV | 运行测试 | + +### 13.2 执行流程 + +每完成一个步骤,按以下流程操作: + +```bash +# 1. 编译项目 +cmake --build build --config Debug + +# 2. 运行测试 +ctest --test-dir build -C Debug --output-on-failure + +# 3. 提交更改 +git add . +git commit -m "test: 添加 D3D12 Device 测试" + +# 4. 推送更改 +git push +``` + +### 13.3 CMake 集成方式 + +采用方案 A:在 `tests/CMakeLists.txt` 中添加子目录引用。 + +在 `tests/CMakeLists.txt` 中添加: +```cmake +# 在现有 add_subdirectory 行之后添加 +add_subdirectory(D3D12) +``` + +创建 `tests/D3D12/CMakeLists.txt` 用于将 `engine/src/RHI/D3D12/test` 添加到构建: +```cmake +# tests/D3D12/CMakeLists.txt +cmake_minimum_required(VERSION 3.15) + +project(D3D12Integration) + +# 将 engine 测试目录添加到父级 CMake +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../engine/src/RHI/D3D12/test ${CMAKE_BINARY_DIR}/D3D12_test) +``` + +### 13.4 测试夹具代码结构 + +基础测试夹具 `D3D12TestFixture.h` 提供以下功能: + +- 全局 D3D12 设备(所有测试共享) +- 每测试周期的命令队列、分配器、命令列表 +- GPU 等待辅助方法 +- 资源清理保证 + +### 13.5 资源路径配置 + +测试资源从 `tests/D3D12/Res/` 获取,通过 CMake 编译定义传递路径: + +```cmake +target_compile_definitions(d3d12_tests PRIVATE + TEST_RESOURCES_DIR="${CMAKE_SOURCE_DIR}/tests/D3D12/Res" +) +``` + +### 13.6 注意事项 + +1. **测试隔离**:每个测试用例应独立创建所需的资源 +2. **资源清理**:在 TearDown 中确保等待 GPU 完成后释放资源 +3. **调试层**:建议在 Debug 构建设中启用 D3D12 Debug Layer +4. **窗口依赖**:SwapChain 等需要窗口的测试放在最后 + +--- + +## 14. 后续改进 + +- [x] 在 `tests/D3D12_engine/test/` 创建测试夹具文件 +- [ ] 实现 Phase 1 核心基础设施测试 +- [ ] 实现 Phase 2 资源管理测试 +- [ ] 实现 Phase 3 渲染管线测试 +- [ ] 实现 Phase 4 视图和命令测试 +- [ ] 实现 Phase 5 高级功能测试 +- [ ] 添加资源泄漏检测工具 +- [ ] 完善渲染结果测试图案 +- [ ] 添加性能基准测试 +- [ ] 配置 CI 自动测试 +- [ ] 支持 Vulkan 后端测试(复用测试夹具抽象) diff --git a/docs/plan/OpenGL后端测试设计.md b/docs/plan/OpenGL后端测试设计.md new file mode 100644 index 0000000..664b2fd --- /dev/null +++ b/docs/plan/OpenGL后端测试设计.md @@ -0,0 +1,1186 @@ +# OpenGL 后端测试设计 + +## 1. 概述 + +本文档描述 XCEngine OpenGL 渲染后端的测试框架设计。OpenGL 后端与 D3D12 后端有显著差异,主要体现在: + +- **窗口依赖**:OpenGL 需要 GLFW 窗口上下文才能执行任何图形操作 +- **对象模型**:使用 GL 句柄(unsigned int)而非 COM 接口 +- **状态管理**:OpenGL 是立即模式渲染,状态通过 GL 函数设置 +- **同步机制**:使用 GLsync 对象进行 GPU/CPU 同步 + +### 1.1 测试目标 + +- 验证 OpenGL 各组件 API 的正确性 +- 确保组件间的协作正常工作 +- 捕获 GL 错误和状态问题 +- 支持持续集成(CI)自动化测试 + +### 1.2 特殊挑战 + +| 挑战 | 说明 | 解决方案 | +|------|------|----------| +| 窗口依赖 | OpenGL 需要 GL 上下文 | 使用无头渲染(headless)或 offscreen 渲染 | +| CI 环境 | 无显示器无法创建窗口 | 使用 OSMesa 或 EGL offscreen 上下文 | +| GL 状态污染 | 全局 GL 状态影响测试 | 每个测试独立设置状态 + 状态重置 | + +### 1.3 与 D3D12 测试对比 + +| 特性 | D3D12 测试 | OpenGL 测试 | +|------|-------------|-------------| +| 设备创建 | D3D12CreateDevice | GLFW + glfwMakeContextCurrent | +| 错误检查 | HRESULT 返回值 | glGetError() | +| 对象类型 | COM 接口 (IUnknown) | GL 句柄 (unsigned int) | +| 资源清理 | Release() | glDelete*() | +| 同步原语 | ID3D12Fence | GLsync | +| 状态管理 | 显式状态对象 | 全局 GL 状态 | + +## 2. 测试目录结构 + +``` +tests/RHI/OpenGL/ +├── CMakeLists.txt # 测试构建配置 +├── fixtures/ +│ ├── OpenGLTestFixture.h # 基础测试夹具 +│ └── OpenGLTestFixture.cpp # 夹具实现 +├── test_device.cpp # OpenGLDevice 测试 +├── test_buffer.cpp # OpenGLBuffer 测试 +├── test_texture.cpp # OpenGLTexture 测试 +├── test_shader.cpp # OpenGLShader 测试 +├── test_pipeline_state.cpp # OpenGLPipelineState 测试 +├── test_vertex_array.cpp # OpenGLVertexArray 测试 +├── test_command_list.cpp # OpenGLCommandList 测试 +├── test_sampler.cpp # OpenGLSampler 测试 +├── test_fence.cpp # OpenGLFence 测试 +├── test_render_target_view.cpp # OpenGLRenderTargetView 测试 +├── test_depth_stencil_view.cpp # OpenGLDepthStencilView 测试 +└── test_swap_chain.cpp # OpenGLSwapChain 测试 +``` + +## 3. 测试夹具设计 + +### 3.1 基础夹具 + +```cpp +// fixtures/OpenGLTestFixture.h +#pragma once + +#include +#include + +namespace XCEngine { +namespace RHI { + +class OpenGLTestFixture : public ::testing::Test { +protected: + static void SetUpTestSuite(); + static void TearDownTestSuite(); + + void SetUp() override; + void TearDown() override; + + GLFWwindow* GetWindow() { return m_window; } + void MakeContextCurrent(); + void DoneContextCurrent(); + + void ClearGLErrors(); + bool CheckGLError(const char* file, int line); + +private: + static GLFWwindow* m_window; + static bool m_contextInitialized; +}; + +} // namespace RHI +} // namespace XCEngine +``` + +### 3.2 设计决策 + +**为什么使用 GLFW 窗口?** + +OpenGL 必须有有效的 GL 上下文才能执行。测试框架使用 GLFW 创建窗口并获取 GL 上下文。在 CI 环境中可能需要使用 OSMesa 或 offscreen 渲染。 + +### 3.3 GL 错误检查辅助 + +```cpp +// fixtures/OpenGLTestFixture.cpp +#include "OpenGLTestFixture.h" + +GLFWwindow* OpenGLTestFixture::m_window = nullptr; +bool OpenGLTestFixture::m_contextInitialized = false; + +void OpenGLTestFixture::SetUpTestSuite() { + if (!glfwInit()) { + GTEST_SKIP() << "Failed to initialize GLFW"; + return; + } + + // 创建隐藏窗口用于测试 + glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + m_window = glfwCreateWindow(640, 480, "OpenGL Tests", nullptr, nullptr); + if (!m_window) { + GTEST_SKIP() << "Failed to create GLFW window"; + glfwTerminate(); + return; + } + + glfwMakeContextCurrent(m_window); + m_contextInitialized = true; +} + +void OpenGLTestFixture::TearDownTestSuite() { + if (m_window) { + glfwDestroyWindow(m_window); + m_window = nullptr; + } + glfwTerminate(); + m_contextInitialized = false; +} + +void OpenGLTestFixture::SetUp() { + if (!m_window || !m_contextInitialized) { + GTEST_SKIP() << "OpenGL context not available"; + return; + } + + glfwMakeContextCurrent(m_window); + ClearGLErrors(); +} + +void OpenGLTestFixture::TearDown() { + // 确保没有未检查的 GL 错误 + GLenum error = glGetError(); + if (error != GL_NO_ERROR) { + // 记录但不一定失败,因为某些 GL 状态改变会产生预期内的错误 + } + + // 重置 GL 状态 + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glUseProgram(0); + glBindVertexArray(0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + glDisable(GL_BLEND); + glDisable(GL_CULL_FACE); + glDisable(GL_SCISSOR_TEST); +} + +void OpenGLTestFixture::ClearGLErrors() { + while (glGetError() != GL_NO_ERROR); +} + +bool OpenGLTestFixture::CheckGLError(const char* file, int line) { + GLenum error = glGetError(); + if (error != GL_NO_ERROR) { + GTEST_MESSAGE_ << "OpenGL Error: " << error + << " (" << GetGLErrorString(error) << ")" + << " at " << file << ":" << line; + return false; + } + return true; +} + +const char* OpenGLTestFixture::GetGLErrorString(GLenum error) { + switch (error) { + case GL_NO_ERROR: return "GL_NO_ERROR"; + case GL_INVALID_ENUM: return "GL_INVALID_ENUM"; + case GL_INVALID_VALUE: return "GL_INVALID_VALUE"; + case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION"; + case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION"; + case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY"; + default: return "Unknown error"; + } +} +``` + +### 3.4 GL 检查宏 + +```cpp +// 在头文件中定义检查宏 +#define GL_CLEAR_ERRORS() \ + do { while (glGetError() != GL_NO_ERROR); } while(0) + +#define GL_CHECK(call) \ + do { \ + call; \ + ASSERT_TRUE(OpenGLTestFixture::CheckGLError(__FILE__, __LINE__)) \ + << "GL error after " << #call; \ + } while(0) + +#define GL_EXPECT_SUCCESS(call) \ + do { \ + call; \ + EXPECT_EQ(glGetError(), GL_NO_ERROR) \ + << "GL error after " << #call; \ + } while(0) +``` + +bool OpenGLTestFixture::CheckGLError(const char* file, int line) { + GLenum error = glGetError(); + if (error != GL_NO_ERROR) { + GTEST_MESSAGE_ << "OpenGL Error: " << error + << " at " << file << ":" << line; + return false; + } + return true; +} + +#define GL_CHECK() ASSERT_TRUE(CheckGLError(__FILE__, __LINE__)) +``` + +## 4. 组件测试详情 + +### 4.1 OpenGLDevice + +**文件**: `test_device.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `CreateRenderWindow_ValidParams` | 窗口创建成功 | +| 初始化 | `InitializeWithExistingWindow` | 现有窗口初始化 | +| 设备信息 | `GetDeviceInfo_ReturnsValid` | 供应商/渲染器信息 | +| 窗口操作 | `SwapBuffers_ClearsScreen` | 交换缓冲区 | +| 窗口操作 | `PollEvents_ProcessesInput` | 事件轮询 | +| 窗口操作 | `ShouldClose_ReturnsBool` | 关闭状态查询 | + +**测试代码示例**: + +```cpp +#include "fixtures/OpenGLTestFixture.h" + +TEST_F(OpenGLTestFixture, Device_CreateWindow_Success) { + OpenGLDevice device; + + bool result = device.CreateRenderWindow(800, 600, "Test Window", false); + + ASSERT_TRUE(result); + ASSERT_NE(device.GetWindow(), nullptr); +} + +TEST_F(OpenGLTestFixture, Device_GetDeviceInfo) { + OpenGLDevice device; + device.CreateRenderWindow(800, 600, "Test", false); + + const auto& info = device.GetDeviceInfo(); + + EXPECT_FALSE(info.vendor.empty()); + EXPECT_FALSE(info.renderer.empty()); + EXPECT_GE(info.majorVersion, 4); + EXPECT_GE(info.minorVersion, 0); +} + +TEST_F(OpenGLTestFixture, Device_PollEvents) { + OpenGLDevice device; + device.CreateRenderWindow(800, 600, "Test", false); + + bool result = device.PollEvents(); + EXPECT_TRUE(result); +} + +TEST_F(OpenGLTestFixture, Device_SwapBuffers) { + OpenGLDevice device; + device.CreateRenderWindow(800, 600, "Test", false); + + device.SwapBuffers(); + + GL_CHECK(); +} +``` + +### 4.2 OpenGLBuffer + +**文件**: `test_buffer.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_VertexBuffer` | 顶点缓冲创建 | +| 初始化 | `Initialize_IndexBuffer` | 索引缓冲创建 | +| 初始化 | `Initialize_UniformBuffer` | Uniform 缓冲创建 | +| 初始化 | `Initialize_Dynamic` | 动态缓冲创建 | +| 绑定 | `Bind_Unbind` | 缓冲绑定/解绑 | +| 绑定 | `BindBase_TargetIndex` | 缓冲绑定到目标索引 | +| 数据操作 | `Map_Unmap` | 数据映射操作 | +| 数据操作 | `SetData_UpdatesContent` | 数据更新 | + +**测试代码示例**: + +```cpp +#include "fixtures/OpenGLTestFixture.h" +#include "OpenGLBuffer.h" + +TEST_F(OpenGLTestFixture, Buffer_InitializeVertexBuffer) { + OpenGLBuffer buffer; + float vertices[] = { 0.0f, 0.0f, 0.5f, 0.5f }; + + bool result = buffer.InitializeVertexBuffer(vertices, sizeof(vertices)); + + ASSERT_TRUE(result); + EXPECT_NE(buffer.GetID(), 0u); + EXPECT_EQ(buffer.GetSize(), sizeof(vertices)); + EXPECT_EQ(buffer.GetType(), OpenGLBufferType::Vertex); +} + +TEST_F(OpenGLTestFixture, Buffer_InitializeIndexBuffer) { + OpenGLBuffer buffer; + unsigned int indices[] = { 0, 1, 2 }; + + bool result = buffer.InitializeIndexBuffer(indices, sizeof(indices)); + + ASSERT_TRUE(result); + EXPECT_NE(buffer.GetID(), 0u); + EXPECT_EQ(buffer.GetSize(), sizeof(indices)); +} + +TEST_F(OpenGLTestFixture, Buffer_InitializeUniformBuffer) { + OpenGLBuffer buffer; + float data[16] = {}; + + bool result = buffer.Initialize( + OpenGLBufferType::Uniform, + sizeof(data), + data, + true + ); + + ASSERT_TRUE(result); + EXPECT_TRUE(buffer.IsDynamic()); + EXPECT_EQ(buffer.GetType(), OpenGLBufferType::Uniform); +} + +TEST_F(OpenGLTestFixture, Buffer_BindUnbind) { + OpenGLBuffer buffer; + buffer.InitializeVertexBuffer(nullptr, 16); + + buffer.Bind(); + GLenum boundBuffer = 0; + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &boundBuffer); + EXPECT_EQ(boundBuffer, static_cast(buffer.GetID())); + + buffer.Unbind(); + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &boundBuffer); + EXPECT_EQ(boundBuffer, 0); +} + +TEST_F(OpenGLTestFixture, Buffer_MapUnmap) { + OpenGLBuffer buffer; + buffer.Initialize(OpenGLBufferType::CopyRead, 256, nullptr, true); + + void* mappedData = buffer.Map(); + ASSERT_NE(mappedData, nullptr); + + memset(mappedData, 0xAB, 256); + + buffer.Unmap(); + + GL_CHECK(); +} +``` + +### 4.3 OpenGLTexture + +**文件**: `test_texture.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_2DTexture` | 2D 纹理创建 | +| 初始化 | `Initialize_3DTexture` | 3D 纹理创建 | +| 初始化 | `Initialize_CubeMap` | 立方体纹理创建 | +| 初始化 | `Initialize_FromFile` | 从文件加载纹理 | +| 绑定 | `Bind_Unbind` | 纹理绑定/解绑 | +| 绑定 | `BindImage_ReadWrite` | 图像绑定 | +| 生成 | `GenerateMipmap` | Mipmap 生成 | +| 参数 | `SetFiltering` | 过滤参数设置 | +| 参数 | `SetWrapping` | 环绕参数设置 | + +### 4.4 OpenGLShader + +**文件**: `test_shader.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 编译 | `Compile_VertexFragment` | 顶点和片段着色器编译 | +| 编译 | `Compile_WithGeometry` | 几何着色器编译 | +| 编译 | `Compile_Compute` | 计算着色器编译 | +| 编译 | `Compile_InvalidSource` | 无效源码编译失败 | +| 链接 | `Link_ValidProgram` | 程序链接成功 | +| 链接 | `Link_MissingStage` | 缺失阶段链接失败 | +| Uniform | `SetInt_SetFloat` | Uniform 设置 | +| Uniform | `SetVec3_SetMat4` | 向量/矩阵 Uniform | + +**测试代码示例**: + +```cpp +#include "fixtures/OpenGLTestFixture.h" +#include "OpenGLShader.h" + +TEST_F(OpenGLTestFixture, Shader_Compile_VertexFragment) { + const char* vertexSource = R"( + #version 460 core + layout(location = 0) in vec3 aPosition; + void main() { + gl_Position = vec4(aPosition, 1.0); + } + )"; + + const char* fragmentSource = R"( + #version 460 core + out vec4 FragColor; + void main() { + FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } + )"; + + OpenGLShader shader; + bool result = shader.Compile(vertexSource, fragmentSource); + + ASSERT_TRUE(result); + EXPECT_TRUE(shader.IsValid()); + EXPECT_NE(shader.GetID(), 0u); +} + +TEST_F(OpenGLTestFixture, Shader_SetUniforms) { + OpenGLShader shader; + const char* vs = R"( + #version 460 core + void main() { gl_Position = vec4(0.0); } + )"; + const char* fs = R"( + #version 460 core + uniform int uIntValue; + uniform float uFloatValue; + uniform vec3 uVec3Value; + uniform mat4 uMat4Value; + out vec4 FragColor; + void main() { FragColor = vec4(1.0); } + )"; + shader.Compile(vs, fs); + + shader.Use(); + + shader.SetInt("uIntValue", 42); + shader.SetFloat("uFloatValue", 3.14f); + shader.SetVec3("uVec3Value", 1.0f, 2.0f, 3.0f); + + float mat[16] = {}; + mat[0] = 1.0f; mat[5] = 1.0f; mat[10] = 1.0f; mat[15] = 1.0f; + shader.SetMat4("uMat4Value", mat); + + GL_CHECK(); +} + +TEST_F(OpenGLTestFixture, Shader_Use_Unbind) { + OpenGLShader shader; + shader.Compile( + "void main() { gl_Position = vec4(0.0); }", + "void main() { }" + ); + + shader.Use(); + + GLint currentProgram = 0; + glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProgram); + EXPECT_EQ(currentProgram, static_cast(shader.GetID())); + + shader.Unbind(); + + glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProgram); + EXPECT_EQ(currentProgram, 0); +} +``` + +### 4.5 OpenGLPipelineState + +**文件**: `test_pipeline_state.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 深度状态 | `SetDepthStencilState` | 深度模板状态 | +| 深度状态 | `ApplyDepthStencil` | 应用深度状态 | +| 混合状态 | `SetBlendState` | 混合状态设置 | +| 混合状态 | `ApplyBlend` | 应用混合状态 | +| 光栅化 | `SetRasterizerState` | 光栅化状态 | +| 视口 | `SetViewport` | 视口设置 | +| 裁剪 | `SetScissor` | 裁剪矩形 | +| 清除 | `SetClearColor` | 清除颜色 | +| 清除 | `Clear_ColorDepthStencil` | 清除颜色/深度/模板 | + +### 4.6 OpenGLVertexArray + +**文件**: `test_vertex_array.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_CreatesVAO` | VAO 创建 | +| 属性 | `AddVertexBuffer` | 顶点缓冲添加 | +| 属性 | `SetIndexBuffer` | 索引缓冲设置 | +| 绑定 | `Bind_Unbind` | VAO 绑定/解绑 | +| 属性 | `GetIndexCount` | 索引数量 | + +### 4.7 OpenGLCommandList + +**文件**: `test_command_list.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 清除 | `Clear_ColorBuffer` | 清除颜色缓冲 | +| 清除 | `Clear_DepthStencil` | 清除深度/模板 | +| 管线 | `SetPipelineState` | 设置管线状态 | +| 顶点 | `SetVertexBuffer` | 设置顶点缓冲 | +| 索引 | `SetIndexBuffer` | 设置索引缓冲 | +| 绘制 | `Draw_Triangles` | 绘制三角形 | +| 绘制 | `DrawIndexed_Indices` | 索引绘制 | +| 绘制 | `DrawInstanced` | 实例化绘制 | +| 计算 | `Dispatch_ComputeShader` | 计算着色器分发 | +| 同步 | `MemoryBarrier` | 内存屏障 | +| 纹理 | `BindTexture` | 纹理绑定 | + +### 4.8 OpenGLSampler + +**文件**: `test_sampler.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_DefaultDesc` | 默认采样器创建 | +| 初始化 | `Initialize_CustomDesc` | 自定义采样器创建 | +| 绑定 | `Bind_Unbind` | 采样器绑定/解绑 | +| 参数 | `GetID_ReturnsValid` | 采样器 ID 有效 | + +### 4.9 OpenGLFence + +**文件**: `test_fence.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_Unsignaled` | 未 signaled 状态创建 | +| 初始化 | `Initialize_Signaled` | signaled 状态创建 | +| 同步 | `Signal_SetsValue` | Signal 设置值 | +| 同步 | `Wait_Blocks` | Wait 阻塞等待 | +| 状态 | `IsSignaled_ReturnsState` | signaled 状态查询 | +| 状态 | `GetStatus_ReturnsCorrect` | 状态查询 | + +**测试代码示例**: + +```cpp +#include "fixtures/OpenGLTestFixture.h" +#include "OpenGLFence.h" + +TEST_F(OpenGLTestFixture, Fence_Initialize_Unsignaled) { + OpenGLFence fence; + + bool result = fence.Initialize(false); + + ASSERT_TRUE(result); + EXPECT_EQ(fence.GetStatus(), FenceStatus::Unsignaled); +} + +TEST_F(OpenGLTestFixture, Fence_Initialize_Signaled) { + OpenGLFence fence; + + bool result = fence.Initialize(true); + + ASSERT_TRUE(result); + // 初始 signaled 状态可能立即完成 +} + +TEST_F(OpenGLTestFixture, Fence_Signal_Wait) { + OpenGLFence fence; + fence.Initialize(false); + + fence.Signal(1); + + // 等待完成 + fence.Wait(1); + + EXPECT_TRUE(fence.IsSignaled()); + EXPECT_EQ(fence.GetCompletedValue(), 1u); +} + +TEST_F(OpenGLTestFixture, Fence_GetStatus) { + OpenGLFence fence; + fence.Initialize(false); + + FenceStatus status = fence.GetStatus(); + EXPECT_TRUE(status == FenceStatus::Signaled || + status == FenceStatus::Unsignaled); +} + +TEST_F(OpenGLFence, Fence_MultipleSignals) { + OpenGLFence fence; + fence.Initialize(false); + + fence.Signal(1); + fence.Wait(1); + + fence.Signal(2); + fence.Wait(2); + + EXPECT_EQ(fence.GetCompletedValue(), 2u); +} +``` + +### 4.10 OpenGLRenderTargetView + +**文件**: `test_render_target_view.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_Texture2D` | 2D 纹理 RTV 创建 | +| 初始化 | `Initialize_Cubemap` | 立方体 RTV 创建 | +| 绑定 | `Bind_Unbind` | RTV 绑定/解绑 | +| 清除 | `Clear_Color` | 清除颜色 | + +### 4.11 OpenGLDepthStencilView + +**文件**: `test_depth_stencil_view.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_Texture2D` | 2D 纹理 DSV 创建 | +| 初始化 | `Initialize_Cubemap` | 立方体 DSV 创建 | +| 绑定 | `Bind_Unbind` | DSV 绑定/解绑 | +| 清除 | `ClearDepthStencil` | 清除深度/模板 | + +### 4.12 OpenGLSwapChain + +**文件**: `test_swap_chain.cpp` + +**可测试 API 点**: + +| 测试类别 | 测试用例 | 验证内容 | +|----------|----------|----------| +| 初始化 | `Initialize_Window` | 交换链初始化 | +| 初始化 | `Initialize_WithSize` | 指定尺寸初始化 | +| 显示 | `Present_VSync` | 垂直同步显示 | +| 显示 | `Present_Immediate` | 立即显示 | +| 调整 | `Resize_ChangesSize` | 调整大小 | +| 属性 | `GetWidth_GetHeight` | 宽高查询 | + +## 5. 测试分类 + +### 5.1 单元测试 + +测试单一 API 的基本功能: + +```cpp +TEST(OpenGL_Buffer, Initialize_VertexBuffer_ReturnsValidID) { + OpenGLBuffer buffer; + float data[] = { 1.0f, 2.0f, 3.0f }; + + bool result = buffer.InitializeVertexBuffer(data, sizeof(data)); + + ASSERT_TRUE(result); + ASSERT_NE(buffer.GetID(), 0u); +} +``` + +### 5.2 集成测试 + +测试多个组件的协作: + +```cpp +TEST(OpenGL_Buffer, UploadToTexture_DataIntegrity) { + // 创建纹理 + OpenGLTexture texture; + texture.Initialize2D(64, 64, 4, nullptr, false); + + // 创建缓冲并上传数据 + OpenGLBuffer buffer; + buffer.Initialize(OpenGLBufferType::CopyRead, 64 * 64 * 4, nullptr, false); + + // 使用命令列表复制 + OpenGLCommandList cmdList; + cmdList.BindTexture(GL_TEXTURE_2D, 0, texture.GetID()); + + GL_CHECK(); +} +``` + +### 5.3 渲染结果测试 + +渲染到帧缓冲并验证像素: + +```cpp +TEST(OpenGL_RenderTarget, ClearColor_VerifyPixelValue) { + // 创建帧缓冲 + OpenGLRenderTargetView rtv; + rtv.Initialize(0); // 默认帧缓冲 + + // 清除为特定颜色 + rtv.Clear(0.25f, 0.5f, 0.75f, 1.0f); + + // 读取像素 + std::vector pixels(4); + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data()); + + // 验证 + EXPECT_NEAR(pixels[0], 64, 2); // R + EXPECT_NEAR(pixels[1], 128, 2); // G + EXPECT_NEAR(pixels[2], 192, 2); // B +} +``` + +## 6. 构建配置 + +### 6.1 CMakeLists.txt + +```cmake +cmake_minimum_required(VERSION 3.15) + +project(OpenGLTests) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# 查找 OpenGL +find_package(OpenGL REQUIRED) + +# 查找 GLFW +find_package(GLFW3 REQUIRED) + +# Google Test +include(FetchContent) +FetchContent_Declare( + googletest + GIT_REPOSITORY https://gitee.com/mirrors/googletest.git + GIT_TAG v1.14.0 +) +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) + +enable_testing() + +# 测试源文件 +set(TEST_SOURCES + test_device.cpp + test_buffer.cpp + test_texture.cpp + test_shader.cpp + test_pipeline_state.cpp + test_vertex_array.cpp + test_command_list.cpp + test_sampler.cpp + test_fence.cpp + test_render_target_view.cpp + test_depth_stencil_view.cpp + test_swap_chain.cpp +) + +# 可执行文件 +add_executable(opengl_tests ${TEST_SOURCES}) + +# 链接库 +target_link_libraries(opengl_tests PRIVATE + OpenGL::GL + GLFW3::GLFW + XCEngine + GTest::gtest + GTest::gtest_main +) + +# 包含目录 +target_include_directories(opengl_tests PRIVATE + ${CMAKE_SOURCE_DIR}/engine/include + ${CMAKE_CURRENT_SOURCE_DIR}/fixtures +) + +# 编译定义 +target_compile_definitions(opengl_tests PRIVATE + GL_GLEXT_PROTOTYPES +) + +# 测试资源路径 +target_compile_definitions(opengl_tests PRIVATE + TEST_RESOURCES_DIR="${CMAKE_SOURCE_DIR}/tests/RHI/OpenGL/Res" +) + +add_test(NAME OpenGLTests COMMAND opengl_tests) +``` + +### 6.2 tests/CMakeLists.txt 更新 + +在 `tests/CMakeLists.txt` 中添加: + +```cmake +# OpenGL Tests +add_subdirectory(RHI/OpenGL) +``` + +## 7. CI 集成 + +### 7.1 GitHub Actions (Linux) + +```yaml +# .github/workflows/opengl-tests.yml +name: OpenGL Tests + +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + libgl1-mesa-dev \ + libglfw3-dev \ + libglm-dev + + - name: Configure + run: cmake -B build -S . -G "Unix Makefiles" + + - name: Build + run: cmake --build build --config Debug + + - name: Run Tests + run: ctest --test-dir build -C Debug --output-on-failure +``` + +### 7.2 GitHub Actions (Windows) + +```yaml +# .github/workflows/opengl-tests-windows.yml +name: OpenGL Tests (Windows) + +on: [push, pull_request] + +jobs: + test: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Configure + run: cmake -B build -S . -G "Visual Studio 17 2022" + + - name: Build + run: cmake --build build --config Debug + + - name: Run Tests + run: ctest --test-dir build -C Debug --output-on-failure +``` + +### 7.3 测试执行流程 + +```bash +# 1. 配置项目 +cmake -B build -S . -G "Unix Makefiles" + +# 2. 编译测试 +cmake --build build --config Debug + +# 3. 运行测试 +./build/tests/RHI/OpenGL/Debug/opengl_tests.exe + +# 或者使用 CTest +ctest --test-dir build -C Debug --output-on-failure + +# 4. 运行特定测试 +./build/tests/RHI/OpenGL/Debug/opengl_tests.exe --gtest_filter=OpenGL_Buffer.* + +# 5. 详细输出 +./build/tests/RHI/OpenGL/Debug/opengl_tests.exe --gtest_also_run_disabled_tests --gtest_print_time=1 +``` + +### 7.4 测试输出示例 + +``` +[==========] Running 54 tests from 1 test suite. +[----------] Global test environment set-up. +[----------] 54 tests from OpenGLTestFixture +[ RUN ] OpenGLTestFixture.Buffer_InitializeVertexBuffer +[ OK ] OpenGLTestFixture.Buffer_InitializeVertexBuffer (12 ms) +[ RUN ] OpenGLTestFixture.Buffer_InitializeIndexBuffer +[ OK ] OpenGLTestFixture.Buffer_InitializeIndexBuffer (8 ms) +... +[----------] Global test environment tear-down +[==========] 54 tests from 1 test suite ran. +[ PASSED ] 54 tests. +``` + +## 8. 测试覆盖矩阵 + +| 组件 | 单元测试 | 集成测试 | 渲染测试 | 性能测试 | +|------|:--------:|:--------:|:--------:|:--------:| +| OpenGLDevice | ✓ | - | - | ✓ | +| OpenGLBuffer | ✓ | ✓ | - | ✓ | +| OpenGLTexture | ✓ | ✓ | ✓ | ✓ | +| OpenGLShader | ✓ | - | - | - | +| OpenGLPipelineState | ✓ | - | - | - | +| OpenGLVertexArray | ✓ | ✓ | - | - | +| OpenGLCommandList | ✓ | ✓ | - | - | +| OpenGLSampler | ✓ | - | - | - | +| OpenGLFence | ✓ | ✓ | - | - | +| OpenGLRenderTargetView | ✓ | - | ✓ | - | +| OpenGLDepthStencilView | ✓ | - | ✓ | - | +| OpenGLSwapChain | - | - | - | - | + +## 9. 测试资源文件 + +### 9.1 资源目录结构 + +``` +tests/RHI/OpenGL/ +├── Res/ +│ ├── Shader/ +│ │ ├── simple_vs.glsl # 简单顶点着色器 +│ │ ├── simple_fs.glsl # 简单片段着色器 +│ │ ├── compute_cs.glsl # 计算着色器 +│ │ └── quad_vs.glsl # Quad 顶点着色器 +│ ├── Texture/ +│ │ ├── test_256x256.png # 测试纹理 +│ │ └── cube_pos_x.jpg # 立方体纹理面 +│ └── Data/ +│ ├── triangle_verts.bin # 三角形顶点数据 +│ └── quad_verts.bin # Quad 顶点数据 +└── ... +``` + +### 9.2 测试着色器示例 + +```glsl +// Res/Shader/simple_vs.glsl +#version 460 core +layout(location = 0) in vec3 aPosition; +layout(location = 1) in vec3 aNormal; +layout(location = 2) in vec2 aTexCoord; + +layout(std140, binding = 0) uniform Camera { + mat4 uModelViewProjection; + mat4 uModel; + mat3 uNormalMatrix; +}; + +out vec3 vPosition; +out vec3 vNormal; +out vec2 vTexCoord; + +void main() { + vPosition = (uModel * vec4(aPosition, 1.0)).xyz; + vNormal = normalize(uNormalMatrix * aNormal); + vTexCoord = aTexCoord; + gl_Position = uModelViewProjection * vec4(aPosition, 1.0); +} +``` + +```glsl +// Res/Shader/simple_fs.glsl +#version 460 core +in vec3 vPosition; +in vec3 vNormal; +in vec2 vTexCoord; + +uniform vec3 uLightDirection; +uniform vec3 uLightColor; +uniform vec3 uAmbientColor; +uniform sampler2D uTexture; + +out vec4 FragColor; + +void main() { + vec3 normal = normalize(vNormal); + float diff = max(dot(normal, uLightDirection), 0.0); + vec3 diffuse = diff * uLightColor; + vec3 ambient = uAmbientColor; + + vec4 texColor = texture(uTexture, vTexCoord); + FragColor = vec4(ambient + diffuse, 1.0) * texColor; +} +``` + +### 9.3 在测试中加载资源 + +```cpp +TEST_F(OpenGLTestFixture, Shader_CompileFromFile) { + OpenGLShader shader; + + std::string vertexPath = std::string(TEST_RESOURCES_DIR) + "/Shader/simple_vs.glsl"; + std::string fragmentPath = std::string(TEST_RESOURCES_DIR) + "/Shader/simple_fs.glsl"; + + // 加载文件内容并编译 + // ... +} + +TEST_F(OpenGLTestFixture, Texture_LoadFromFile) { + OpenGLTexture texture; + + std::string texturePath = std::string(TEST_RESOURCES_DIR) + "/Texture/test_256x256.png"; + + bool result = texture.LoadFromFile(texturePath.c_str()); + + ASSERT_TRUE(result); + EXPECT_EQ(texture.GetWidth(), 256); + EXPECT_EQ(texture.GetHeight(), 256); +} +``` + +## 9. 实现优先级 + +### Phase 1: 核心基础设施 + +1. **OpenGLDevice** - 窗口和上下文管理 +2. **OpenGLBuffer** - 基础数据缓冲 +3. **OpenGLFence** - 同步基础 + +### Phase 2: 资源管理 + +4. **OpenGLTexture** - 纹理资源 +5. **OpenGLSampler** - 采样器 + +### Phase 3: 渲染管线 + +6. **OpenGLShader** - 着色器编译 +7. **OpenGLPipelineState** - 管线状态 +8. **OpenGLVertexArray** - 顶点数组 + +### Phase 4: 命令与视图 + +9. **OpenGLCommandList** - 命令录制 +10. **OpenGLRenderTargetView** - 渲染目标 +11. **OpenGLDepthStencilView** - 深度模板 + +### Phase 5: 窗口管理 + +12. **OpenGLSwapChain** - 交换链 + +## 10. 特殊考虑 + +### 10.1 无头渲染 + +在 CI 环境中没有显示器,需要使用 offscreen 渲染: + +```cpp +// 使用 OSMesa 创建 offscreen 上下文 +#ifdef __linux__ + glfwWindowHint(GLFW_PLATFORM, GLFW_PLATFORM_OSMESA); +#endif + +// 或使用 Mesa 的软件渲染llvmpipe +// 运行测试时设置环境变量: +// MESA_GL_VERSION_OVERRIDE=4.6 MESA_GALLIUM_DRIVER=llvmpipe +``` + +### 10.2 GL 状态隔离 + +OpenGL 状态是全局的,测试需要注意: + +- 每个测试开始时重置 GL 状态 +- 使用独立的 VAO 隔离顶点数组状态 +- 使用独立的 Program 隔离着色器状态 +- 测试结束后清理所有绑定的对象 + +```cpp +void OpenGLTestFixture::ResetGLState() { + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + glUseProgram(0); + + glBindVertexArray(0); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + glActiveTexture(GL_TEXTURE0); + for (int i = 0; i < 16; ++i) { + glBindTexture(GL_TEXTURE_2D, 0); + } + + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + glDisable(GL_BLEND); + glDisable(GL_CULL_FACE); + glDisable(GL_SCISSOR_TEST); + + glDepthFunc(GL_LESS); + glStencilFunc(GL_ALWAYS, 0, 0xFF, 0xFF); + glBlendFunc(GL_ONE, GL_ZERO); +} +``` + +### 10.3 错误处理 + +```cpp +// 检查所有 GL 调用后的错误 +#define GL_CALL(call) \ + call; \ + CheckGLError(__FILE__, __LINE__, #call) + +// 期望成功的调用 +#define GL_EXPECT_SUCCESS(call) \ + do { \ + call; \ + EXPECT_EQ(glGetError(), GL_NO_ERROR) \ + << "GL error after " << #call; \ + } while(0) + +// 检查特定错误 +#define GL_EXPECT_ERROR(expectedError, call) \ + do { \ + glGetError(); /* clear existing */ \ + call; \ + EXPECT_EQ(glGetError(), expectedError) \ + << "Expected " << #expectedError << " after " << #call; \ + } while(0) +``` + +### 10.4 跨平台考虑 + +| 平台 | 特殊处理 | +|------|----------| +| Windows | 使用 WGL 创建 GL 上下文 | +| Linux | 使用 GLX 或 Mesa 软件渲染 | +| macOS | 使用 Cocoa/NSOpenGL(需要特殊处理) | +| CI/无头 | 使用 OSMesa 或 EGL offscreen | + +## 11. 后续改进 + +- [ ] 实现 Phase 1 核心基础设施测试 +- [ ] 实现 Phase 2 资源管理测试 +- [ ] 实现 Phase 3 渲染管线测试 +- [ ] 实现 Phase 4 命令与视图测试 +- [ ] 实现 Phase 5 窗口管理测试 +- [ ] 添加资源泄漏检测工具 +- [ ] 添加性能基准测试 +- [ ] 配置 CI 自动测试 +- [ ] 支持 macOS 测试 + +--- + +**文档版本**:1.1 +**创建日期**:2026年3月17日 +**最后更新**:2026年3月17日 diff --git a/docs/plan/OpenGL测试实施计划.md b/docs/plan/OpenGL测试实施计划.md new file mode 100644 index 0000000..65344b5 --- /dev/null +++ b/docs/plan/OpenGL测试实施计划.md @@ -0,0 +1,410 @@ +# OpenGL 测试实施计划 + +## 1. 概述 + +本文档是 `docs/OpenGL后端测试设计.md` 的实施细化计划,基于设计文档中的 5 阶段实现优先级,结合 D3D12 测试经验(54 个测试)制定。 + +### 1.1 目标 + +- 搭建完整的 OpenGL 后端测试框架 +- 实现与 D3D12 对齐的 54+ 个测试用例 +- 确保 CI 环境可用 +- 支持无头渲染(headless)测试 + +### 1.2 测试组件总览 + +| # | 组件 | 测试数量 | 文件 | 优先级 | +|---|------|:--------:|------|:------:| +| 1 | OpenGLDevice | 6 | test_device.cpp | Phase 1 | +| 2 | OpenGLBuffer | 6 | test_buffer.cpp | Phase 1 | +| 3 | OpenGLFence | 5 | test_fence.cpp | Phase 1 | +| 4 | OpenGLTexture | 5 | test_texture.cpp | Phase 2 | +| 5 | OpenGLSampler | 4 | test_sampler.cpp | Phase 2 | +| 6 | OpenGLShader | 4 | test_shader.cpp | Phase 3 | +| 7 | OpenGLPipelineState | 3 | test_pipeline_state.cpp | Phase 3 | +| 8 | OpenGLVertexArray | 4 | test_vertex_array.cpp | Phase 3 | +| 9 | OpenGLCommandList | 8 | test_command_list.cpp | Phase 4 | +| 10 | OpenGLRenderTargetView | 4 | test_render_target_view.cpp | Phase 4 | +| 11 | OpenGLDepthStencilView | 4 | test_depth_stencil_view.cpp | Phase 4 | +| 12 | OpenGLSwapChain | 3 | test_swap_chain.cpp | Phase 5 | +| **总计** | | **56** | | | + +--- + +## 2. 实施阶段 + +### Phase 1: 核心基础设施(约 1 天) + +#### 2.1 创建目录结构 + +``` +tests/RHI/OpenGL/ +├── CMakeLists.txt +├── fixtures/ +│ ├── OpenGLTestFixture.h +│ └── OpenGLTestFixture.cpp +└── Res/ + ├── Shader/ + ├── Texture/ + └── Data/ +``` + +#### 2.2 实现测试夹具 + +**OpenGLTestFixture** 是所有测试的基础: + +| 功能 | 描述 | +|------|------| +| `SetUpTestSuite()` | 创建隐藏 GLFW 窗口和 GL 上下文 | +| `TearDownTestSuite()` | 销毁窗口,终止 GLFW | +| `SetUp()` | 确保上下文激活,清除 GL 错误 | +| `TearDown()` | 重置 GL 状态,检查泄漏 | +| `CheckGLError()` | 检查并报告 GL 错误 | + +**GL 错误检查宏**: + +```cpp +#define GL_CLEAR_ERRORS() do { while (glGetError() != GL_NO_ERROR); } while(0) +#define GL_CHECK(call) do { call; ASSERT_TRUE(CheckGLError(__FILE__, __LINE__)); } while(0) +#define GL_EXPECT_SUCCESS(call) do { call; EXPECT_EQ(glGetError(), GL_NO_ERROR); } while(0) +``` + +#### 2.3 OpenGLDevice 测试(6 个) + +| 测试用例 | 验证内容 | +|----------|----------| +| `CreateRenderWindow_ValidParams` | 窗口创建成功 | +| `CreateRenderWindow_DebugMode` | 调试模式创建 | +| `InitializeWithExistingWindow` | 现有窗口初始化 | +| `GetDeviceInfo_ReturnsValid` | 供应商/渲染器/版本信息 | +| `SwapBuffers_NoErrors` | 交换缓冲区无错误 | +| `PollEvents_ReturnsTrue` | 事件轮询正常 | + +#### 2.4 OpenGLBuffer 测试(6 个) + +| 测试用例 | 验证内容 | +|----------|----------| +| `Initialize_VertexBuffer` | 顶点缓冲创建 | +| `Initialize_IndexBuffer` | 索引缓冲创建 | +| `Initialize_UniformBuffer` | Uniform 缓冲创建 | +| `Initialize_Dynamic` | 动态缓冲创建 | +| `Bind_Unbind` | 缓冲绑定/解绑 | +| `Map_Unmap` | 数据映射操作 | + +#### 2.5 OpenGLFence 测试(5 个) + +| 测试用例 | 验证内容 | +|----------|----------| +| `Initialize_Unsignaled` | 未 signaled 状态创建 | +| `Initialize_Signaled` | signaled 状态创建 | +| `Signal_SetsValue` | Signal 设置值 | +| `Wait_Blocks` | Wait 阻塞等待 | +| `IsSignaled_ReturnsState` | signaled 状态查询 | + +#### 2.6 验证步骤 + +```bash +# 构建 +cmake --build build --config Debug + +# 运行测试 +./build/tests/RHI/OpenGL/Debug/opengl_tests.exe --gtest_filter=OpenGLTestFixture.Device*:OpenGLTestFixture.Buffer*:OpenGLTestFixture.Fence* + +# 预期结果 +[==========] 17 tests from OpenGLTestFixture +[ PASSED ] 17 tests +``` + +--- + +### Phase 2: 资源管理(约 1 天) + +#### 2.7 OpenGLTexture 测试(5 个) + +| 测试用例 | 验证内容 | +|----------|----------| +| `Initialize_2DTexture` | 2D 纹理创建 | +| `Initialize_CubeMap` | 立方体纹理创建 | +| `Bind_Unbind` | 纹理绑定/解绑 | +| `GenerateMipmap` | Mipmap 生成 | +| `SetFiltering_SetWrapping` | 过滤/环绕参数 | + +#### 2.8 OpenGLSampler 测试(4 个) + +| 测试用例 | 验证内容 | +|----------|----------| +| `Initialize_Default` | 默认采样器创建 | +| `Initialize_Custom` | 自定义采样器创建 | +| `Bind_Unbind` | 采样器绑定/解绑 | +| `GetID_ReturnsValid` | 采样器 ID 有效 | + +#### 2.9 验证步骤 + +```bash +# 运行资源管理测试 +./build/tests/RHI/OpenGL/Debug/opengl_tests.exe --gtest_filter=OpenGLTestFixture.Texture*:OpenGLTestFixture.Sampler* + +# 预期结果 +[==========] 9 tests from OpenGLTestFixture +[ PASSED ] 9 tests +``` + +--- + +### Phase 3: 渲染管线(约 1.5 天) + +#### 2.10 OpenGLShader 测试(4 个) + +| 测试用例 | 验证内容 | +|----------|----------| +| `Compile_VertexFragment` | 顶点和片段着色器编译 | +| `Compile_WithGeometry` | 几何着色器编译 | +| `Compile_InvalidSource` | 无效源码编译失败 | +| `SetUniforms` | Uniform 设置 (int/float/vec3/mat4) | + +#### 2.11 OpenGLPipelineState 测试(3 个) + +| 测试用例 | 验证内容 | +|----------|----------| +| `SetDepthStencilState` | 深度/模板状态设置 | +| `SetBlendState` | 混合状态设置 | +| `SetViewport_SetScissor` | 视口/裁剪矩形 | + +#### 2.12 OpenGLVertexArray 测试(4 个) + +| 测试用例 | 验证内容 | +|----------|----------| +| `Initialize_CreatesVAO` | VAO 创建 | +| `AddVertexBuffer` | 顶点缓冲添加 | +| `SetIndexBuffer` | 索引缓冲设置 | +| `Bind_Unbind` | VAO 绑定/解绑 | + +#### 2.13 验证步骤 + +```bash +# 运行渲染管线测试 +./build/tests/RHI/OpenGL/Debug/opengl_tests.exe --gtest_filter=OpenGLTestFixture.Shader*:OpenGLTestFixture.PipelineState*:OpenGLTestFixture.VertexArray* + +# 预期结果 +[==========] 11 tests from OpenGLTestFixture +[ PASSED ] 11 tests +``` + +--- + +### Phase 4: 命令与视图(约 1.5 天) + +#### 2.14 OpenGLCommandList 测试(8 个) + +| 测试用例 | 验证内容 | +|----------|----------| +| `Clear_ColorBuffer` | 清除颜色缓冲 | +| `Clear_DepthStencil` | 清除深度/模板 | +| `SetVertexBuffer` | 设置顶点缓冲 | +| `SetIndexBuffer` | 设置索引缓冲 | +| `Draw_Triangles` | 绘制三角形 | +| `DrawIndexed_Indices` | 索引绘制 | +| `DrawInstanced` | 实例化绘制 | +| `Dispatch_ComputeShader` | 计算着色器分发 | + +#### 2.15 OpenGLRenderTargetView 测试(4 个) + +| 测试用例 | 验证内容 | +|----------|----------| +| `Initialize_Texture2D` | 2D 纹理 RTV 创建 | +| `Initialize_Default` | 默认帧缓冲 RTV | +| `Bind_Unbind` | RTV 绑定/解绑 | +| `Clear_Color` | 清除颜色 | + +#### 2.16 OpenGLDepthStencilView 测试(4 个) + +| 测试用例 | 验证内容 | +|----------|----------| +| `Initialize_Texture2D` | 2D 纹理 DSV 创建 | +| `Initialize_DepthOnly` | 仅深度 DSV | +| `Bind_Unbind` | DSV 绑定/解绑 | +| `ClearDepthStencil` | 清除深度/模板 | + +#### 2.17 验证步骤 + +```bash +# 运行命令与视图测试 +./build/tests/RHI/OpenGL/Debug/opengl_tests.exe --gtest_filter=OpenGLTestFixture.CommandList*:OpenGLTestFixture.RenderTargetView*:OpenGLTestFixture.DepthStencilView* + +# 预期结果 +[==========] 16 tests from OpenGLTestFixture +[ PASSED ] 16 tests +``` + +--- + +### Phase 5: 窗口管理(约 0.5 天) + +#### 2.18 OpenGLSwapChain 测试(3 个) + +| 测试用例 | 验证内容 | +|----------|----------| +| `Initialize_Window` | 交换链初始化 | +| `Present_VSync` | 垂直同步显示 | +| `Resize_ChangesSize` | 调整大小 | + +#### 2.19 验证步骤 + +```bash +# 运行窗口管理测试 +./build/tests/RHI/OpenGL/Debug/opengl_tests.exe --gtest_filter=OpenGLTestFixture.SwapChain* + +# 预期结果 +[==========] 3 tests from OpenGLTestFixture +[ PASSED ] 3 tests +``` + +--- + +## 3. 完整验证 + +### 3.1 运行所有测试 + +```bash +# 完整测试 +cmake --build build --config Debug +ctest --test-dir build -C Debug --output-on-failure + +# 预期结果 +[==========] 56 tests from 1 test suite. +[ PASSED ] 56 tests +``` + +### 3.2 测试分类统计 + +| 分类 | 数量 | 占比 | +|------|:----:|:----:| +| 初始化测试 | 18 | 32% | +| 绑定/解绑测试 | 10 | 18% | +| 数据操作测试 | 8 | 14% | +| 状态设置测试 | 10 | 18% | +| 绘制/执行测试 | 10 | 18% | + +--- + +## 4. CI 配置 + +### 4.1 GitHub Actions + +```yaml +# .github/workflows/opengl-tests.yml +name: OpenGL Tests + +on: [push, pull_request] + +jobs: + test: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - name: Configure + run: cmake -B build -S . -G "Visual Studio 17 2022" + + - name: Build + run: cmake --build build --config Debug + + - name: Run Tests + run: ctest --test-dir build -C Debug --output-on-failure +``` + +### 4.2 Linux CI(可选) + +Linux 下需要配置 Mesa 软件渲染: + +```yaml +- name: Run Tests + env: + MESA_GL_VERSION_OVERRIDE: 4.6 + MESA_GALLIUM_DRIVER: llvmpipe + run: ctest --test-dir build -C Debug --output-on-failure +``` + +--- + +## 5. 任务清单 + +### 阶段 1:基础设施 + +- [ ] 1.1 创建 `tests/RHI/OpenGL/CMakeLists.txt` +- [ ] 1.2 创建 `tests/RHI/OpenGL/fixtures/OpenGLTestFixture.h` +- [ ] 1.3 创建 `tests/RHI/OpenGL/fixtures/OpenGLTestFixture.cpp` +- [ ] 1.4 实现 `test_device.cpp`(6 个测试) +- [ ] 1.5 实现 `test_buffer.cpp`(6 个测试) +- [ ] 1.6 实现 `test_fence.cpp`(5 个测试) +- [ ] 1.7 构建验证(17 个测试) + +### 阶段 2:资源管理 + +- [ ] 2.1 实现 `test_texture.cpp`(5 个测试) +- [ ] 2.2 实现 `test_sampler.cpp`(4 个测试) +- [ ] 2.3 构建验证(9 个测试) + +### 阶段 3:渲染管线 + +- [ ] 3.1 实现 `test_shader.cpp`(4 个测试) +- [ ] 3.2 实现 `test_pipeline_state.cpp`(3 个测试) +- [ ] 3.3 实现 `test_vertex_array.cpp`(4 个测试) +- [ ] 3.4 构建验证(11 个测试) + +### 阶段 4:命令与视图 + +- [ ] 4.1 实现 `test_command_list.cpp`(8 个测试) +- [ ] 4.2 实现 `test_render_target_view.cpp`(4 个测试) +- [ ] 4.3 实现 `test_depth_stencil_view.cpp`(4 个测试) +- [ ] 4.4 构建验证(16 个测试) + +### 阶段 5:窗口管理 + +- [ ] 5.1 实现 `test_swap_chain.cpp`(3 个测试) +- [ ] 5.2 完整测试验证(56 个测试) +- [ ] 5.3 提交并推送 + +--- + +## 6. 关键注意事项 + +### 6.1 窗口依赖 + +- OpenGL 必须有 GLFW 窗口上下文 +- 使用 `GLFW_VISIBLE = GLFW_FALSE` 创建隐藏窗口 +- 每个测试前 `glfwMakeContextCurrent()` + +### 6.2 GL 状态污染 + +- OpenGL 状态是全局的,必须隔离 +- `TearDown()` 中重置所有 GL 状态 +- 测试结束后 `glBindBuffer(..., 0)` 等 + +### 6.3 错误检查 + +- 使用 `GL_CHECK()` 宏验证每个 GL 调用 +- 测试开始时 `GL_CLEAR_ERRORS()` +- 捕获 GL 错误并转换为测试失败 + +### 6.4 与 D3D12 对齐 + +- 保持相同的测试数量级(54+) +- 使用相同的 TEST_F 宏 +- 遵循相同的命名约定 + +--- + +## 7. 后续工作 + +- [ ] 资源泄漏检测工具 +- [ ] 性能基准测试 +- [ ] 截图对比测试 +- [ ] Linux CI 配置 +- [ ] macOS 支持 + +--- + +**文档版本**:1.0 +**创建日期**:2026年3月17日 +**基于文档**:`docs/OpenGL后端测试设计.md`、`tests/RHI/D3D12/` diff --git a/docs/plan/RHI抽象层设计与实现.md b/docs/plan/RHI抽象层设计与实现.md new file mode 100644 index 0000000..1e7dbab --- /dev/null +++ b/docs/plan/RHI抽象层设计与实现.md @@ -0,0 +1,1069 @@ +# 跨平台 RHI 渲染架构设计文档 +## 1. 项目背景 +本项目旨在参考 Unity 渲染架构,为已有的 **OpenGL** 和 **Direct3D 12** 图形 API 后端设计统一的**渲染硬件抽象层(RHI)**,屏蔽 API 差异,实现引擎上层逻辑与底层图形 API 的解耦。 + +### 现有项目结构 +``` +engine/ +├── include/XCEngine/RHI/ +│ ├── Enums.h # 通用枚举定义 +│ ├── Types.h # 通用结构体定义 +│ ├── D3D12/ # D3D12 后端实现 +│ └── OpenGL/ # OpenGL 后端实现 +└── src/RHI/ + ├── D3D12/ # D3D12 源码 + └── OpenGL/ # OpenGL 源码 +``` + + +## 2. 核心设计理念 +### 2.1 总体原则 +**求同存异,分层抽象,特性降级,底层逃逸** +- **求同存异**:优先提取 API 共性作为核心抽象,差异部分通过模拟/降级处理 +- **分层抽象**:通过清晰的层级结构隔离 API 差异 +- **特性降级**:对高级特性提供能力检测和替代方案 +- **底层逃逸**:允许直接访问原生 API 以满足极端需求 + +### 2.2 差异分类与处理策略 +| 差异类型 | 典型示例 | 处理方案 | +|----------|----------|----------| +| 概念命名不同但本质相似 | D3D12 `CommandList` ≈ OpenGL 状态机绘制 | 直接统一抽象 | +| 显式控制 vs 隐式管理 | D3D12 `DescriptorHeap` vs OpenGL 纹理单元 | 提供"自动模式"+"显式模式" | +| API 独有高级特性 | D3D12 光线追踪、网格着色器 | 特性检测 + 降级方案 + 底层逃逸 | + + +## 3. RHI 分层架构 +### 3.1 通用分层模型 +``` +┌─────────────────────────────────┐ +│ 引擎功能层(场景/材质/光照) │ +├─────────────────────────────────┤ +│ 渲染管线层(SRP/Render Graph) │ +├─────────────────────────────────┤ +│ RHI 抽象层(统一接口) │ ← 核心设计重点 +├─────────────────────────────────┤ +│ API 后端层(D3D12/OpenGL) │ +├─────────────────────────────────┤ +│ 驱动/硬件层 │ +└─────────────────────────────────┘ +``` + +### 3.2 层级职责说明 +1. **引擎功能层**:提供场景管理、材质系统、光照等高级功能接口 +2. **渲染管线层**:定义渲染流程(前向/延迟渲染) +3. **RHI 抽象层**:统一图形 API 接口,屏蔽差异 +4. **API 后端层**:针对具体 API 的实现 +5. **驱动/硬件层**:最终执行渲染指令 + + +## 4. RHI 抽象基类设计 +### 4.1 目录结构调整建议 +``` +include/XCEngine/RHI/ +├── RHIEnums.h # 通用枚举 +├── RHITypes.h # 通用结构体 +├── RHICapabilities.h # 硬件能力检测 +├── RHIDevice.h # 设备抽象(核心入口) +├── RHICommandQueue.h # 命令队列抽象 +├── RHICommandList.h # 命令列表抽象 +├── RHIBuffer.h # 缓冲区抽象 +├── RHITexture.h # 纹理抽象 +├── RHIShader.h # 着色器抽象 +├── RHIPipelineLayout.h # 管线布局抽象(替代 RootSignature) +├── RHIPipelineState.h # 管线状态抽象 +├── RHISwapChain.h # 交换链抽象 +├── RHIFence.h # 同步栅栏抽象 +├── RHIDescriptorPool.h # 描述符池抽象 +└── RHIFactory.h # RHI 工厂类 +``` + +### 4.2 核心抽象基类定义 +#### 4.2.1 通用类型定义(Types.h) +```cpp +#pragma once +#include + +// 通用资源格式 +enum class RHIFormat { + R8G8B8A8_UNORM, + D32_FLOAT, + // ... 其他格式 +}; + +// 缓冲区用途 +enum class RHIBufferUsage { + VertexBuffer, + IndexBuffer, + ConstantBuffer, + // ... 其他用途 +}; + +// 通用缓冲区描述 +struct RHIBufferDesc { + uint64_t size; + RHIBufferUsage usage; + // ... 其他参数 +}; + +// 通用纹理描述 +struct RHITextureDesc { + uint32_t width; + uint32_t height; + RHIFormat format; + // ... 其他参数 +}; + +// 通用渲染通道描述 +struct RHIRenderPassDesc { + struct Attachment { + RHITexture* texture; + float clearColor[4]; + // ... 其他参数 + } colorAttachments[8]; + uint32_t colorAttachmentCount; + Attachment depthStencilAttachment; + // ... 其他参数 +}; +``` + +#### 4.2.2 硬件能力检测(RHICapabilities.h) +```cpp +#pragma once + +struct RHICapabilities { + bool bSupportsRayTracing = false; + bool bSupportsMeshShaders = false; + bool bSupportsExplicitMultiThreading = false; + // ... 其他特性 +}; +``` + +#### 4.2.3 设备抽象(RHIDevice.h) +```cpp +#pragma once +#include "Types.h" +#include "RHICapabilities.h" + +class RHISwapChain; +class RHICommandQueue; +class RHIBuffer; +class RHITexture; + +class RHIDevice { +public: + virtual ~RHIDevice() = default; + + // 初始化设备 + virtual bool Initialize(const RHIDeviceDesc& desc) = 0; + + // 资源创建接口 + virtual RHIBuffer* CreateBuffer(const RHIBufferDesc& desc) = 0; + virtual RHITexture* CreateTexture(const RHITextureDesc& desc) = 0; + virtual RHICommandQueue* CreateCommandQueue(const RHICommandQueueDesc& desc) = 0; + virtual RHISwapChain* CreateSwapChain(const RHISwapChainDesc& desc) = 0; + + // 硬件能力查询 + virtual const RHICapabilities& GetCapabilities() const = 0; + + // 底层逃逸口(谨慎使用) + virtual void* GetNativeDevice() = 0; + + // 清理 + virtual void Shutdown() = 0; +}; +``` + +#### 4.2.4 命令列表抽象(RHICommandList.h) +```cpp +#pragma once +#include "Types.h" + +class RHIBuffer; +class RHITexture; +class RHIPipelineState; + +class RHICommandList { +public: + virtual ~RHICommandList() = default; + + // 命令录制 + virtual void Begin() = 0; + virtual void End() = 0; + + // 渲染通道 + virtual void BeginRenderPass(const RHIRenderPassDesc& desc) = 0; + virtual void EndRenderPass() = 0; + + // 状态设置 + virtual void SetPipelineState(RHIPipelineState* pso) = 0; + virtual void SetVertexBuffers(uint32_t slot, RHIBuffer* const* buffers, uint32_t count) = 0; + virtual void SetIndexBuffer(RHIBuffer* buffer, RHIFormat format, uint32_t offset) = 0; + + // 绘制命令 + virtual void DrawIndexed(uint32_t indexCount, uint32_t instanceCount, + uint32_t startIndex, int32_t baseVertex, + uint32_t startInstance) = 0; + + // 资源拷贝 + virtual void CopyBuffer(RHIBuffer* dst, RHIBuffer* src, uint64_t size) = 0; +}; +``` + +#### 4.2.5 管线布局抽象(RHIPipelineLayout.h) +```cpp +#pragma once +#include "Types.h" + +// 管线布局描述(统一描述资源绑定规则) +struct RHIPipelineLayoutDesc { + uint32_t constantBufferCount; + uint32_t textureCount; + uint32_t samplerCount; + // ... 其他参数 +}; + +class RHIPipelineLayout { +public: + virtual ~RHIPipelineLayout() = default; + // 具体实现由后端处理 +}; +``` + +#### 4.2.6 RHI 工厂类(RHIFactory.h) +```cpp +#pragma once +#include "RHIDevice.h" +#include + +enum class RHIType { + D3D12, + OpenGL, + // 未来扩展 Vulkan/Metal +}; + +class RHIFactory { +public: + // 根据类型创建 RHI 设备 + static RHIDevice* CreateRHIDevice(RHIType type); + + // 根据字符串选择(从配置文件读取) + static RHIDevice* CreateRHIDevice(const std::string& typeName); +}; +``` + + +## 5. 核心差异处理方案 + +### 5.1 缓冲区(RHIBuffer)抽象设计 + +#### 5.1.1 现有实现对比 + +| 功能 | D3D12Buffer | OpenGLBuffer | 处理方案 | +|------|-------------|--------------|----------| +| 初始化参数 | 需要 device + heapType | 不需要 | 后端各自实现初始化逻辑 | +| 句柄类型 | `ID3D12Resource*` | `GLuint` | 统一返回 `void*`,底层逃逸 | +| Map/Unmap | `Map()` / `Unmap()` | `glMapBuffer` | 后端各自实现 | +| 上传数据 | `UpdateData()` | `SetData()` | 统一为 `SetData()` | +| 获取大小 | `GetSize()` | `GetSize()` | 通用 | +| Vertex Stride | 显式存储 `m_stride` | VAO 管理 | 基类提供接口 | +| 资源状态 | `ResourceStates` 显式管理 | 无 | D3D12 维护,OpenGL 透明 | + +#### 5.1.2 抽象接口定义 + +```cpp +// engine/include/XCEngine/RHI/RHIBuffer.h +class RHIBuffer { +public: + virtual ~RHIBuffer() = default; + + // 数据操作 + virtual void* Map() = 0; + virtual void Unmap() = 0; + virtual void SetData(const void* data, size_t size, size_t offset = 0) = 0; + + // 属性查询 + virtual uint64_t GetSize() const = 0; + virtual BufferType GetBufferType() const = 0; + virtual void SetBufferType(BufferType type) = 0; + virtual uint32_t GetStride() const = 0; + virtual void SetStride(uint32_t stride) = 0; + + // 底层逃逸 + virtual void* GetNativeHandle() = 0; + + // 调试 + virtual const std::string& GetName() const = 0; + virtual void SetName(const std::string& name) = 0; + + // 生命周期 + virtual void Shutdown() = 0; +}; +``` + +#### 5.1.3 差异处理策略 + +1. **初始化参数差异** + - D3D12:在 `CreateBuffer()` 时由 Device 传入 device 参数,内部调用 `Initialize(device, size, ...)` + - OpenGL:直接调用 `Initialize(type, size, data, dynamic)`,不需要 device + +2. **句柄类型差异** + - `GetNativeHandle()` 返回 `void*` + - D3D12 后端:`return m_resource.Get();` + - OpenGL 后端:`return (void*)(uintptr_t)m_buffer;` + +3. **Vertex Stride** + - D3D12:显式存储在 `m_stride` + - OpenGL:在 VertexArray 中管理,可在基类中提供接口 + +4. **Device 创建接口** + ```cpp + // RHIDevice 中 + virtual RHIBuffer* CreateBuffer(const BufferDesc& desc) = 0; + + // D3D12Device 实现 + RHIBuffer* CreateBuffer(const BufferDesc& desc) override { + auto* buffer = new D3D12Buffer(); + buffer->Initialize(m_device.Get(), desc.size, ...); + return buffer; + } + + // OpenGLDevice 实现 + RHIBuffer* CreateBuffer(const BufferDesc& desc) override { + auto* buffer = new OpenGLBuffer(); + buffer->Initialize(glType, desc.size, ...); + return buffer; + } + ``` + +### 5.2 纹理(RHITexture)抽象设计 + +#### 5.2.1 设计理念对应 + +| 差异点 | 设计理念 | 处理方案 | +|--------|---------|---------| +| 初始化参数差异 | 求同存异 | 后端各自实现初始化,基类定义统一创建接口 | +| 句柄类型差异 | 底层逃逸 | 统一返回 void*,通过 GetNativeHandle() 获取原生类型 | +| 资源状态管理 | 特性降级 | D3D12 显式管理 ResourceStates,OpenGL 无需管理(透明) | +| 格式枚举差异 | 求同存异 | 基类统一 Format 枚举,后端映射到各自格式 | + +#### 5.2.2 现有实现对比 + +| 功能 | D3D12Texture | OpenGLTexture | 处理方案 | +|------|--------------|---------------|----------| +| 初始化参数 | device + resource desc | type + dimensions + format | 后端各自实现 | +| 句柄类型 | `ID3D12Resource*` | `GLuint` | 统一返回 `void*` | +| 尺寸获取 | GetWidth/Height/Depth | 同上 | 统一接口 | +| Mip Levels | GetMipLevels() | GetMipLevels() | 通用 | +| 格式 | DXGI_FORMAT | OpenGLFormat | 基类统一 Format | +| 纹理类型 | TextureType enum | OpenGLTextureType enum | 基类统一 TextureType | +| 绑定 | 通过 DescriptorHeap | glBindTexture | 后端实现 Bind() | +| Mipmap 生成 | 需手动计算 | glGenerateMipmap | 后端实现 | +| 资源状态 | ResourceStates | 无 | D3D12 维护,OpenGL 透明 | +| 深度纹理 | InitializeDepthStencil() | 普通纹理 | 后端实现 | + +#### 5.2.3 抽象接口定义 + +```cpp +class RHITexture { +public: + virtual ~RHITexture() = default; + + // 属性(求同存异) + virtual uint32_t GetWidth() const = 0; + virtual uint32_t GetHeight() const = 0; + virtual uint32_t GetDepth() const = 0; + virtual uint32_t GetMipLevels() const = 0; + virtual Format GetFormat() const = 0; + virtual TextureType GetTextureType() const = 0; + + // 资源状态(特性降级) + virtual ResourceStates GetState() const = 0; + virtual void SetState(ResourceStates state) = 0; + + // 底层逃逸 + virtual void* GetNativeHandle() = 0; + + // 调试 + virtual const std::string& GetName() const = 0; + virtual void SetName(const std::string& name) = 0; + + // 生命周期 + virtual void Shutdown() = 0; +}; +``` + +#### 5.2.4 差异处理策略 + +1. **初始化参数差异(求同存异)** + - D3D12:需要 device + resource desc + - OpenGL:需要 type + dimensions + format + - 解决:Device 的 CreateTexture() 统一接收 TextureDesc,后端各自实现 Initialize() + +2. **句柄类型差异(底层逃逸)** + - `GetNativeHandle()` 返回 `void*` + - D3D12:`return m_resource.Get();` + - OpenGL:`return reinterpret_cast(static_cast(m_texture));` + +3. **资源状态管理(特性降级)** + - D3D12:显式 ResourceStates 管理,需要转换 barrier + - OpenGL:无资源状态概念 + - 解决:基类提供 GetState/SetState,D3D12 实现具体逻辑,OpenGL 空实现 + +4. **格式枚举差异(求同存异)** + - D3D12:DXGI_FORMAT + - OpenGL:OpenGLFormat + - 解决:基类统一使用 Format 枚举,后端内部映射 + +### 5.7 着色器(RHIShader)抽象设计 + +#### 5.7.1 设计理念对应 + +| 差异点 | 设计理念 | 处理方案 | +|--------|---------|---------| +| 编译方式差异 | 求同存异 | 统一 Compile 接口,后端各自实现 | +| 句柄类型差异 | 底层逃逸 | 统一返回 void* | +| Uniform 设置 | 特性降级 | OpenGL 实现,D3D12 空实现 | +| 绑定方式 | 求同存异 | 基类提供 Bind/Unbind,后端实现 | + +#### 5.7.2 现有实现对比 + +| 功能 | D3D12Shader | OpenGLShader | 处理方案 | +|------|-------------|--------------|----------| +| 编译 | CompileFromFile/Compile | 同上 | 统一接口 | +| 字节码/Program | ID3DBlob | GLuint | 统一 void* | +| 类型 | ShaderType | 自有 enum | 基类统一 | +| Uniform 设置 | 无 | SetInt/SetFloat... | OpenGL 实现,D3D12 空 | +| 绑定 | 通过 CommandList | Use()/Bind() | 基类提供 Bind/Unbind | + +#### 5.7.3 抽象接口定义 + +```cpp +class RHIShader { +public: + virtual ~RHIShader() = default; + + // 编译(求同存异) + virtual bool CompileFromFile(const wchar_t* filePath, const char* entryPoint, const char* target) = 0; + virtual bool Compile(const void* sourceData, size_t sourceSize, const char* entryPoint, const char* target) = 0; + + // 属性 + virtual ShaderType GetType() const = 0; + virtual bool IsValid() const = 0; + + // 绑定(求同存异) + virtual void Bind() = 0; + virtual void Unbind() = 0; + + // 底层逃逸 + virtual void* GetNativeHandle() = 0; + + // Uniform 设置(特性降级) + virtual void SetInt(const char* name, int value) = 0; + virtual void SetFloat(const char* name, float value) = 0; + virtual void SetVec3(const char* name, float x, float y, float z) = 0; + virtual void SetVec4(const char* name, float x, float y, float z, float w) = 0; + virtual void SetMat4(const char* name, const float* value) = 0; + + // 生命周期 + virtual void Shutdown() = 0; +}; +``` + +#### 5.7.4 差异处理策略 + +1. **编译方式差异(求同存异)** + - D3D12:需要 entry point + target(如 "vs_6_0") + - OpenGL:根据 source 类型自动判断 + - 解决:统一 Compile 接口,后端各自处理 + +2. **句柄类型差异(底层逃逸)** + - D3D12:ID3DBlob + - OpenGL:GLuint (program) + - 解决:GetNativeHandle() 返回 void* + +3. **Uniform 设置(特性降级)** + - D3D12:通过 RootSignature/CBV 设置,不在 Shader 类 + - OpenGL:通过 glUniform* 设置 + - 解决:D3D12 实现为空,OpenGL 实现具体逻辑 + +4. **绑定方式** + - D3D12:通过 CommandList->SetPipelineState + - OpenGL:glUseProgram + - 解决:基类提供 Bind/Unbind 接口 + +### 5.8 采样器(RHISampler)抽象设计 + +#### 5.8.1 设计理念对应 + +| 差异点 | 设计理念 | 处理方案 | +|--------|---------|---------| +| 初始化参数差异 | 求同存异 | 后端各自实现初始化 | +| 句柄类型差异 | 底层逃逸 | 统一返回 void* | +| 绑定方式 | 求同存异 | 基类提供 Bind/Unbind | + +#### 5.8.2 现有实现对比 + +| 功能 | D3D12Sampler | OpenGLSampler | +|------|--------------|---------------| +| 初始化 | Initialize(device, desc) | Initialize(desc) | +| 销毁 | Shutdown() | Shutdown() | +| 绑定 | 通过 DescriptorHeap | Bind(unit) | +| 句柄 | GetNativeHandle() | GetID() | + +#### 5.8.3 抽象接口定义 + +```cpp +class RHISampler { +public: + virtual ~RHISampler() = default; + + virtual void Shutdown() = 0; + + virtual void Bind(unsigned int unit) = 0; + virtual void Unbind(unsigned int unit) = 0; + + virtual void* GetNativeHandle() = 0; + virtual unsigned int GetID() = 0; +}; +``` + +#### 5.8.4 差异处理策略 + +1. **初始化参数差异(求同存异)** + - D3D12:需要 device 参数 + - OpenGL:不需要 device + - 解决:Device 的 CreateSampler() 统一接收 SamplerDesc,后端各自实现 Initialize() + +2. **句柄类型差异(底层逃逸)** + - D3D12:通过 DescriptorHeap 管理 + - OpenGL:GLuint + - 解决:GetNativeHandle() 返回 void* + +### 5.9 同步栅栏(RHIFence)抽象设计 + +#### 5.9.1 设计理念对应 + +| 差异点 | 设计理念 | 处理方案 | +|--------|---------|---------| +| 初始化参数差异 | 求同存异 | 后端各自实现初始化 | +| 句柄类型差异 | 底层逃逸 | 统一返回 void* | +| 状态查询 | 求同存异 | 统一 IsSignaled/GetCompletedValue 接口 | + +#### 5.9.2 现有实现对比 + +| 功能 | D3D12Fence | OpenGLFence | +|------|-------------|-------------| +| 初始化 | Initialize(device, value) | Initialize(signaled) | +| Signal | Signal(value) | Signal()/Signal(value) | +| Wait | Wait(value) | Wait(timeoutNs) | +| 状态 | GetCompletedValue() | IsSignaled()/GetStatus() | +| 句柄 | ID3D12Fence* | GLsync | + +#### 5.9.3 抽象接口定义 + +```cpp +class RHIFence { +public: + virtual ~RHIFence() = default; + + virtual void Shutdown() = 0; + + virtual void Signal(uint64_t value) = 0; + virtual void Wait(uint64_t value) = 0; + virtual uint64_t GetCompletedValue() = 0; + virtual bool IsSignaled() const = 0; + + virtual void* GetNativeHandle() = 0; +}; +``` + +#### 5.9.4 差异处理策略 + +1. **初始化参数差异(求同存异)** + - D3D12:需要 device 参数 + - OpenGL:不需要 device + - 解决:后端各自实现 Initialize() + +2. **句柄类型差异(底层逃逸)** + - D3D12:ID3D12Fence* + - OpenGL:GLsync + - 解决:GetNativeHandle() 返回 void* + +### 5.10 设备(RHIDevice)抽象设计 + +#### 5.10.1 设计理念对应 + +| 差异点 | 设计理念 | 处理方案 | +|--------|---------|---------| +| 初始化参数差异 | 求同存异 | 统一 Initialize 接口,后端各自处理 | +| 工厂方法差异 | 特性降级 | D3D12 实现,OpenGL 返回 nullptr | +| 窗口管理差异 | 特性降级 | OpenGL 有,D3D12 通过 SwapChain 处理 | +| 适配器枚举差异 | 特性降级 | D3D12 实现,OpenGL 空实现 | +| 底层设备类型差异 | 底层逃逸 | 统一返回 void* | + +#### 5.10.2 现有实现对比 + +| 功能 | D3D12Device | OpenGLDevice | 处理方案 | +|------|--------------|---------------|----------| +| 初始化 | Initialize(debugLayer) | CreateRenderWindow/InitializeWithExistingWindow | 统一 Initialize | +| 关闭 | Shutdown() | Shutdown() | 统一 | +| 获取设备 | GetDevice() | 无 | GetNativeHandle 统一 | +| 适配器信息 | GetAdapterInfo() | GetDeviceInfo() | 统一 GetDeviceInfo | +| 工厂方法 | CreateBuffer/Texture/Shader... | 无 | OpenGL 返回 nullptr | +| 窗口管理 | 通过 SwapChain | GetWindow/SwapBuffers/PollEvents | OpenGL 有,D3D12 无 | + +#### 5.10.3 抽象接口定义 + +```cpp +class RHIDevice { +public: + virtual ~RHIDevice() = default; + + virtual bool Initialize(const RHIDeviceDesc& desc) = 0; + virtual void Shutdown() = 0; + + virtual const RHIDeviceInfo& GetDeviceInfo() const = 0; + virtual const RHICapabilities& GetCapabilities() const = 0; + + virtual RHIBuffer* CreateBuffer(const BufferDesc& desc) = 0; + virtual RHITexture* CreateTexture(const TextureDesc& desc) = 0; + virtual RHIShader* CompileShader(const ShaderCompileDesc& desc) = 0; + virtual RHISampler* CreateSampler(const SamplerDesc& desc) = 0; + virtual RHIFence* CreateFence(const FenceDesc& desc) = 0; + + virtual void* GetNativeDevice() = 0; + + virtual void* GetNativeHandle() const = 0; +}; +``` + +#### 5.10.4 差异处理策略 + +1. **初始化参数差异(求同存异)** + - D3D12:`Initialize(enableDebugLayer)` + - OpenGL:`CreateRenderWindow` / `InitializeWithExistingWindow` + - 解决:统一 `Initialize(const RHIDeviceDesc& desc)` 接口,Desc 中包含窗口参数 + +2. **工厂方法差异(特性降级)** + - D3D12:有完整的工厂方法 + - OpenGL:资源直接用 glGen* 创建,没有工厂方法 + - 解决:OpenGL 后端返回 nullptr,上层需直接创建 OpenGL 资源 + +3. **窗口管理差异(特性降级)** + - OpenGL:直接管理窗口,有 GetWindow/SwapBuffers/PollEvents + - D3D12:通过 SwapChain 处理 + - 解决:OpenGL 提供窗口管理接口,D3D12 空实现 + +4. **适配器枚举差异(特性降级)** + - D3D12:支持 EnumerateAdapters + - OpenGL:无此概念 + - 解决:D3D12 实现具体功能,OpenGL 返回空 + +5. **底层设备类型差异(底层逃逸)** + - D3D12:ID3D12Device* + - OpenGL:无对等概念 + - 解决:GetNativeDevice() 返回 void*,OpenGL 返回 nullptr 或窗口句柄 +- **D3D12**:显式 `RootSignature` 定义资源绑定规则 +- **OpenGL**:隐式通过 `glUniformLocation`、`glBindTextureUnit` 绑定 +- **解决方案**: + - 用 `RHIPipelineLayout` 统一抽象 + - D3D12 后端:内部创建 `ID3D12RootSignature` + - OpenGL 后端:存储绑定点数量,绘制时自动调用 `glBind*` + +### 5.4 描述符堆 vs OpenGL 纹理单元 +- **D3D12**:显式 `DescriptorHeap` 管理资源视图 +- **OpenGL**:隐式通过 `glActiveTexture` 绑定 +- **解决方案**: + - 用 `RHIDescriptorPool` 统一抽象 + - 提供"自动模式"(默认)和"显式模式"(可选) + - D3D12 后端:从堆分配槽位,更新描述符 + - OpenGL 后端:维护绑定点计数器,绘制时自动绑定 + +### 5.5 多线程命令录制 +- **D3D12**:原生支持多线程录制不同 `CommandList` +- **OpenGL**:状态机模型,单线程上下文 +- **解决方案**: + - 抽象层统一提供多线程接口 + - D3D12 后端:真·并行提交 + - OpenGL 后端:命令缓冲队列,单线程回放 + +### 5.6 高级特性(光线追踪等) +- **解决方案**: + 1. **特性检测**:通过 `RHICapabilities` 查询支持情况 + 2. **降级方案**:不支持时用传统路径替代 + 3. **底层逃逸**:通过 `GetNativeDevice()` 直接访问原生 API + + +### 5.11 命令队列(RHICommandQueue)抽象设计 + +#### 5.11.1 设计理念对应 + +| 差异点 | 设计理念 | 处理方案 | +|--------|---------|---------| +| 初始化参数差异 | 求同存异 | 后端各自实现初始化 | +| 执行命令差异 | 特性降级 | D3D12 实现,OpenGL 空实现 | +| 同步机制差异 | 特性降级 | D3D12 实现,OpenGL 空实现 | +| 句柄类型差异 | 底层逃逸 | 统一返回 void* | + +#### 5.11.2 现有实现对比 + +| 功能 | D3D12CommandQueue | OpenGL | 处理方案 | +|------|-------------------|--------|----------| +| 初始化 | Initialize(device, type) | 无 | OpenGL 空实现 | +| 执行命令 | ExecuteCommandLists() | 无 | OpenGL 空实现 | +| 信号同步 | Signal/Wait | 无 | OpenGL 空实现 | +| 空闲等待 | WaitForIdle() | 无 | OpenGL 空实现 | +| 句柄 | ID3D12CommandQueue* | 无 | GetNativeHandle | + +#### 5.11.3 抽象接口定义 + +```cpp +class RHICommandQueue { +public: + virtual ~RHICommandQueue() = default; + + virtual void Shutdown() = 0; + + virtual void ExecuteCommandLists(uint32_t count, void** lists) = 0; + virtual void Signal(RHIFence* fence, uint64_t value) = 0; + virtual void Wait(RHIFence* fence, uint64_t value) = 0; + virtual uint64_t GetCompletedValue() = 0; + virtual void WaitForIdle() = 0; + + virtual CommandQueueType GetType() const = 0; + virtual uint64_t GetTimestampFrequency() const = 0; + + virtual void* GetNativeHandle() = 0; +}; +``` + +#### 5.11.4 差异处理策略 + +1. **初始化参数差异(求同存异)** + - D3D12:需要 device + type 参数 + - OpenGL:无对等概念 + - 解决:Device 的 CreateCommandQueue() 统一接收 CommandQueueDesc + +2. **执行命令差异(特性降级)** + - D3D12:ExecuteCommandLists() 提交命令列表 + - OpenGL:状态机模型,无命令队列概念 + - 解决:OpenGL 空实现 + +3. **同步机制差异(特性降级)** + - D3D12:Signal/Wait/Fence 完整实现 + - OpenGL:无对等概念 + - 解决:OpenGL 空实现 + +4. **句柄类型差异(底层逃逸)** + - D3D12:ID3D12CommandQueue* + - OpenGL:无对等概念 + - 解决:GetNativeHandle() 返回 void* + + +### 5.12 命令列表(RHICommandList)抽象设计 + +#### 5.12.1 设计理念对应 + +| 差异点 | 设计理念 | 处理方案 | +|--------|---------|---------| +| 资源状态转换 | 特性降级 | D3D12 实现转换,OpenGL 空实现 | +| 绑定方式 | 求同存异 | 统一接口,后端各自实现 | +| 渲染目标 | 求同存异 | 统一接口,后端各自实现 | + +#### 5.12.2 现有实现对比 + +| 功能 | D3D12CommandList | OpenGLCommandList | 处理方案 | +|------|-------------------|-------------------|----------| +| 资源转换 | TransitionBarrier | glBarrier | 统一 TransitionBarrier | +| PSO 设置 | SetPipelineState | UseShader | 统一 SetPipelineState | +| 视口/裁剪 | SetViewport/ScissorRect | SetViewport/Scissor | 统一 | +| 顶点缓冲 | SetVertexBuffer | BindVertexArray | 统一 | +| 索引缓冲 | SetIndexBuffer | BindVertexArray | 统一 | +| 绘制 | Draw/DrawIndexed | Draw/DrawIndexed | 统一 | +| 渲染目标 | SetRenderTargets | glBindFramebuffer | 统一 | +| 清除 | ClearRenderTargetView | Clear | 统一 | +| 复制 | CopyResource | CopyImageSubData | 统一 | +| 计算 | Dispatch | DispatchCompute | 统一 | + +#### 5.12.3 抽象接口定义 + +```cpp +class RHICommandList { +public: + virtual ~RHICommandList() = default; + + virtual void Shutdown() = 0; + + virtual void Reset() = 0; + virtual void Close() = 0; + + virtual void TransitionBarrier(void* resource, ResourceStates stateBefore, ResourceStates stateAfter) = 0; + + virtual void SetPipelineState(void* pso) = 0; + virtual void SetViewport(const Viewport& viewport) = 0; + virtual void SetScissorRect(const Rect& rect) = 0; + virtual void SetRenderTargets(uint32_t count, void** renderTargets, void* depthStencil = nullptr) = 0; + + virtual void SetVertexBuffer(uint32_t slot, void* buffer, uint64_t offset, uint32_t stride) = 0; + virtual void SetIndexBuffer(void* buffer, uint64_t offset, Format format) = 0; + + virtual void Draw(uint32_t vertexCount, uint32_t instanceCount = 1, uint32_t startVertex = 0, uint32_t startInstance = 0) = 0; + virtual void DrawIndexed(uint32_t indexCount, uint32_t instanceCount = 1, uint32_t startIndex = 0, int32_t baseVertex = 0, uint32_t startInstance = 0) = 0; + + virtual void Clear(float r, float g, float b, float a, uint32_t buffers) = 0; + virtual void ClearRenderTarget(void* renderTarget, const float color[4]) = 0; + virtual void ClearDepthStencil(void* depthStencil, float depth, uint8_t stencil) = 0; + + virtual void CopyResource(void* dst, void* src) = 0; + + virtual void Dispatch(uint32_t x, uint32_t y, uint32_t z) = 0; +}; +``` + +#### 5.12.4 差异处理策略 + +1. **资源状态转换(特性降级)** + - D3D12:显式 TransitionBarrier 管理资源状态 + - OpenGL:无资源状态概念 + - 解决:D3D12 实现转换,OpenGL 空实现 + +2. **绑定方式(求同存异)** + - D3D12:通过 DescriptorHeap 和 RootSignature + - OpenGL:通过 glBind* 和 VAO + - 解决:统一 Set* 接口,后端各自实现 + +3. **渲染目标(求同存异)** + - D3D12:SetRenderTargets 设置渲染目标视图 + - OpenGL:glBindFramebuffer 绑定帧缓冲 + - 解决:统一 SetRenderTargets 接口 + + +### 5.13 交换链(RHISwapChain)抽象设计 + +#### 5.13.1 设计理念对应 + +| 差异点 | 设计理念 | 处理方案 | +|--------|---------|---------| +| 初始化参数差异 | 求同存异 | 统一 Desc,后端各自处理 | +| 窗口管理差异 | 特性降级 | OpenGL 有,D3D12 无 | +| 呈现方式差异 | 求同存异 | 统一 Present 接口 | + +#### 5.13.2 现有实现对比 + +| 功能 | D3D12SwapChain | OpenGLSwapChain | 处理方案 | +|------|----------------|------------------|----------| +| 初始化 | factory/queue/hwnd | window | 统一 Initialize(Desc) | +| 后缓冲 | GetBackBuffer() | 无 | 通过 GetCurrentBackBuffer | +| 显示 | Present(sync, flags) | Present() | 统一 Present() | +| 调整大小 | Resize(w, h) | Resize(w, h) | 统一 | +| 窗口事件 | 无 | ShouldClose/PollEvents | OpenGL 实现 | + +#### 5.13.3 抽象接口定义 + +```cpp +class RHISwapChain { +public: + virtual ~RHISwapChain() = default; + + virtual void Shutdown() = 0; + + virtual uint32_t GetCurrentBackBufferIndex() const = 0; + virtual RHITexture* GetCurrentBackBuffer() = 0; + virtual void Present(uint32_t syncInterval = 1, uint32_t flags = 0) = 0; + virtual void Resize(uint32_t width, uint32_t height) = 0; + + virtual bool ShouldClose() const = 0; + virtual void SetShouldClose(bool shouldClose) = 0; + virtual void PollEvents() = 0; +}; +``` + +#### 5.13.4 差异处理策略 + +1. **初始化参数差异(求同存异)** + - D3D12:factory + commandQueue + hwnd + - OpenGL:window + - 解决:Device 的 CreateSwapChain() 统一接收 SwapChainDesc + +2. **窗口管理差异(特性降级)** + - OpenGL:ShouldClose/PollEvents + - D3D12:无 + - 解决:OpenGL 实现具体功能,D3D12 空实现 + +3. **呈现方式差异(求同存异)** + - D3D12:Present(syncInterval, flags) + - OpenGL:Present() / SwapBuffers() + - 解决:统一 Present(syncInterval, flags) + + +### 5.14 管线状态(RHIPipelineState)抽象设计 + +#### 5.14.1 设计理念对应 + +| 差异点 | 设计理念 | 处理方案 | +|--------|---------|---------| +| 初始化差异 | 求同存异 | 后端各自处理 | +| 状态管理差异 | 特性降级 | D3D12 实现状态块,OpenGL 分离状态 | +| 绑定方式差异 | 求同存异 | 统一 Bind 接口 | + +#### 5.14.2 现有实现对比 + +| 功能 | D3D12PipelineState | OpenGLPipelineState | 处理方案 | +|------|-------------------|-------------------|----------| +| 初始化 | device + desc | 构造函数 | 后端各自处理 | +| 状态设置 | 单一 PSO 对象 | 分离状态对象 | 后端各自处理 | +| 绑定 | CommandList->SetPipelineState | AttachShader/Apply | 统一 Bind | +| 句柄 | ID3D12PipelineState* | GLuint (program) | 统一 void* | + +#### 5.14.3 抽象接口定义 + +```cpp +class RHIPipelineState { +public: + virtual ~RHIPipelineState() = default; + + virtual void Shutdown() = 0; + + virtual void Bind() = 0; + virtual void Unbind() = 0; + + virtual void* GetNativeHandle() = 0; + virtual PipelineType GetType() const = 0; +}; +``` + +#### 5.14.4 差异处理策略 + +1. **初始化差异(求同存异)** + - D3D12:device + D3D12_GRAPHICS_PIPELINE_STATE_DESC + - OpenGL:通过 SetDepthStencilState/BlendState/RasterizerState + - 解决:Device 的 CreatePipelineState() 统一接收 PipelineStateDesc + +2. **状态管理差异(特性降级)** + - D3D12:单一 PSO 对象包含所有状态 + - OpenGL:分离的状态对象 + - 解决:后端各自实现,基类提供统一 Bind/Unbind + +3. **绑定方式差异(求同存异)** + - D3D12:通过 CommandList->SetPipelineState + - OpenGL:AttachShader + Apply + - 解决:统一 Bind/Unbind 接口 + + +## 6. 后端实现示例 +### 6.1 D3D12 设备实现(D3D12Device.h) +```cpp +#pragma once +#include "../RHIDevice.h" +#include "D3D12Common.h" + +class D3D12Device : public RHIDevice { +public: + virtual bool Initialize(const RHIDeviceDesc& desc) override; + virtual RHIBuffer* CreateBuffer(const RHIBufferDesc& desc) override; + virtual RHITexture* CreateTexture(const RHITextureDesc& desc) override; + virtual RHICommandQueue* CreateCommandQueue(const RHICommandQueueDesc& desc) override; + virtual RHISwapChain* CreateSwapChain(const RHISwapChainDesc& desc) override; + virtual const RHICapabilities& GetCapabilities() const override; + virtual void* GetNativeDevice() override { return m_pd3d12Device; } + virtual void Shutdown() override; + + // D3D12 特有接口 + ID3D12Device* GetD3D12Device() const { return m_pd3d12Device; } + +private: + ID3D12Device* m_pd3d12Device = nullptr; + ID3D12CommandQueue* m_pd3d12CommandQueue = nullptr; + RHICapabilities m_capabilities; +}; +``` + +### 6.2 OpenGL 设备实现(OpenGLDevice.h) +```cpp +#pragma once +#include "../RHIDevice.h" +#include "OpenGLCommon.h" + +class OpenGLDevice : public RHIDevice { +public: + virtual bool Initialize(const RHIDeviceDesc& desc) override; + virtual RHIBuffer* CreateBuffer(const RHIBufferDesc& desc) override; + virtual RHITexture* CreateTexture(const RHITextureDesc& desc) override; + virtual RHICommandQueue* CreateCommandQueue(const RHICommandQueueDesc& desc) override; + virtual RHISwapChain* CreateSwapChain(const RHISwapChainDesc& desc) override; + virtual const RHICapabilities& GetCapabilities() const override; + virtual void* GetNativeDevice() override { return m_context; } + virtual void Shutdown() override; + + // OpenGL 特有接口 + HGLRC GetContext() const { return m_context; } + +private: + HGLRC m_context = nullptr; + RHICapabilities m_capabilities; +}; +``` + + +## 7. 测试用例示例 +### 7.1 最小渲染循环测试 +```cpp +#include "XCEngine/RHI/RHIFactory.h" +#include "XCEngine/RHI/RHIDevice.h" +#include "XCEngine/RHI/RHISwapChain.h" +#include "XCEngine/RHI/RHICommandList.h" + +int main() { + // 1. 创建 RHI 设备(可切换 D3D12/OpenGL) + RHIDevice* pDevice = RHIFactory::CreateRHIDevice(RHIType::D3D12); + pDevice->Initialize(RHIDeviceDesc{...}); + + // 2. 创建交换链和命令队列 + RHISwapChain* pSwapChain = pDevice->CreateSwapChain(RHISwapChainDesc{...}); + RHICommandQueue* pCommandQueue = pDevice->CreateCommandQueue(RHICommandQueueDesc{...}); + RHICommandList* pCommandList = pDevice->CreateCommandList(RHICommandListDesc{...}); + + // 3. 渲染循环 + while (!ShouldQuit()) { + // 录制命令 + pCommandList->Begin(); + + // 清屏 + RHIRenderPassDesc renderPassDesc = {}; + renderPassDesc.colorAttachments[0].texture = pSwapChain->GetCurrentBackBuffer(); + renderPassDesc.colorAttachments[0].loadOp = RHIRenderPassLoadOp::Clear; + renderPassDesc.colorAttachments[0].clearColor = {0.2f, 0.4f, 0.8f, 1.0f}; + pCommandList->BeginRenderPass(renderPassDesc); + pCommandList->EndRenderPass(); + + // 提交命令 + pCommandList->End(); + pCommandQueue->SubmitCommandList(pCommandList); + + // 呈现 + pSwapChain->Present(); + } + + // 4. 清理 + pDevice->Shutdown(); + delete pDevice; + return 0; +} +``` + + +## 8. 下一步行动指南 +1. **补全抽象基类**:重点实现 `RHIDevice`、`RHICommandList`、`RHIPipelineLayout` +2. **改造现有后端**:让 `D3D12Device`、`OpenGLDevice` 继承抽象基类并实现接口 +3. **实现工厂类**:完成 `RHIFactory` 以支持动态切换后端 +4. **测试验证**:用最小渲染循环测试 D3D12 和 OpenGL 后端 +5. **扩展功能**:逐步添加资源管理、着色器跨平台、多线程渲染等功能 + + +## 9. 关键注意事项 +- **上层只调用抽象接口**:绝不直接访问 D3D12/OpenGL 特有类 +- **合理使用底层逃逸**:仅在必要时使用 `GetNativeDevice()`,并注明破坏跨平台性 +- **优先保证核心功能**:先实现 90% 常用功能的统一抽象,再处理高级特性 +- **保持设计可扩展**:为未来支持 Vulkan/Metal 预留空间 + +需要我帮你细化某个具体模块的实现代码吗? \ No newline at end of file diff --git a/docs/plan/TESTING.md b/docs/plan/TESTING.md new file mode 100644 index 0000000..27223a4 --- /dev/null +++ b/docs/plan/TESTING.md @@ -0,0 +1,285 @@ +# XCEngine 测试体系文档 + +> **版本**: 1.0 +> **日期**: 2026-03-13 + +--- + +## 1. 测试架构 + +``` +tests/ +├── CMakeLists.txt # 测试构建配置 +├── run_tests.cmake # 测试运行脚本 +├── fixtures/ # 测试夹具 +│ └── MathFixtures.h +├── math/ # Math 单元测试 +│ ├── CMakeLists.txt +│ ├── test_vector.cpp +│ ├── test_matrix.cpp +│ ├── test_quaternion.cpp +│ └── test_geometry.cpp +├── core/ # Core 测试 +├── threading/ # 线程测试 +├── memory/ # 内存测试 +├── containers/ # 容器测试 +└── rendering/ # 渲染测试 + ├── unit/ # 单元测试 + ├── integration/ # 集成测试 + └── screenshots/ # 参考图 +``` + +--- + +## 2. 测试分类 + +| 类型 | 目录 | 目的 | 运行频率 | +|------|------|------|---------| +| **Unit Test** | `tests/*/` | 验证单个函数/类 | 每次提交 | +| **Integration Test** | `tests/rendering/integration/` | 验证多模块协作 | 每次提交 | +| **Benchmark** | `tests/benchmark/` | 性能回归检测 | 每日/每周 | +| **Screenshot Test** | `tests/rendering/screenshots/` | 渲染正确性 | 每次提交 | + +--- + +## 3. 测试命名规范 + +```cpp +// 格式: test_<模块>_<功能>_<场景> +TEST(Math_Vector3, Dot_TwoVectors_ReturnsCorrectValue) { } +TEST(Math_Vector3, Normalize_ZeroVector_ReturnsZeroVector) { } +TEST(Math_Matrix4, Inverse_Identity_ReturnsIdentity) { } +TEST(Math_Matrix4, TRS_Decompose_RecoversOriginalValues) { } +TEST(Math_Quaternion, Slerp_ShortestPath_InterpolatesCorrectly) { } + +// 边界情况 +TEST(Math_Vector3, Normalize_ZeroVector_DoesNotCrash) { } +TEST(Math_Matrix4, Inverse_SingularMatrix_ReturnsIdentity) { } +``` + +--- + +## 4. 断言规范 + +### 4.1 浮点数比较 + +```cpp +// 必须使用容差 +EXPECT_NEAR(actual, expected, 1e-5f); +ASSERT_FLOAT_EQ(actual, expected); // gtest 内部有容差 + +// 数组比较 +for (int i = 0; i < 4; i++) { + EXPECT_NEAR(actual.m[i], expected.m[i], 1e-5f); +} +``` + +### 4.2 常用断言 + +```cpp +EXPECT_TRUE(condition); +EXPECT_FALSE(condition); +EXPECT_EQ(actual, expected); +EXPECT_NE(actual, expected); +EXPECT_STREQ(actual, expected); +EXPECT_THROW(expression, exception_type); +``` + +--- + +## 5. 测试夹具 (Fixture) + +```cpp +class MathFixture : public ::testing::Test { +protected: + void SetUp() override { + v1 = Vector3(1, 0, 0); + v2 = Vector3(0, 1, 0); + v3 = Vector3(1, 1, 1); + + m1 = Matrix4x4::Identity(); + m2 = Matrix4x4::Translation(Vector3(1, 2, 3)); + } + + Vector3 v1, v2, v3; + Matrix4x4 m1, m2; + const float epsilon = 1e-5f; +}; + +TEST_F(MathFixture, Dot_OrthogonalVectors_ReturnsZero) { + EXPECT_FLOAT_EQ(Vector3::Dot(v1, v2), 0.0f); +} +``` + +--- + +## 6. 参数化测试 + +```cpp +class MatrixInverseTest : public ::testing::TestWithParam {}; + +INSTANTIATE_TEST_SUITE_P( + InverseCases, + MatrixInverseTest, + testing::Values( + Matrix4x4::Identity(), + Matrix4x4::Translation(Vector3(1,2,3)), + Matrix4x4::Scale(Vector3(2,2,2)) + ) +); + +TEST_P(MatrixInverseTest, InverseOfInverse_EqualsOriginal) { + Matrix4x4 original = GetParam(); + Matrix4x4 inverted = original.Inverse(); + Matrix4x4 recovered = inverted.Inverse(); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + EXPECT_NEAR(original.m[i][j], recovered.m[i][j], 1e-4f); + } + } +} +``` + +--- + +## 7. Math 测试用例 + +### 7.1 Vector2/3/4 测试 + +| 测试类别 | 测试用例 | +|---------|---------| +| **构造** | 默认构造、参数构造、从 Vector3 构造 | +| **运算** | 加、减、乘、除、点积、叉积 | +| **归一化** | Normalize、Normalized、Magnitude、SqrMagnitude | +| **插值** | Lerp、MoveTowards | +| **投影** | Project、ProjectOnPlane | +| **角度** | Angle、Reflect | + +### 7.2 Matrix 测试 + +| 测试类别 | 测试用例 | +|---------|---------| +| **构造** | Identity、Zero | +| **变换** | Translation、Rotation、Scale、TRS | +| **相机** | LookAt、Perspective、Orthographic | +| **运算** | 乘法、点乘、叉乘 | +| **分解** | Inverse、Transpose、Determinant、Decompose | + +### 7.3 Quaternion 测试 + +| 测试类别 | 测试用例 | +|---------|---------| +| **构造** | Identity、FromAxisAngle、FromEulerAngles | +| **转换** | ToEulerAngles、ToMatrix4x4、FromRotationMatrix | +| **插值** | Slerp | +| **运算** | 乘法和逆 | + +### 7.4 几何测试 + +| 测试类型 | 测试用例 | +|---------|---------| +| **Ray** | GetPoint、Intersects(Sphere/Box/Plane) | +| **Sphere** | Contains、Intersects | +| **Box** | Contains、Intersects | +| **Plane** | FromPoints、GetDistanceToPoint、Intersects | +| **Frustum** | Contains(Point/Sphere/Bounds)、Intersects | +| **Bounds** | GetMinMax、Intersects、Contains、Encapsulate | + +--- + +## 8. 构建与运行 + +### 8.1 构建测试 + +```bash +# 创建构建目录 +mkdir build && cd build + +# 配置 CMake +cmake .. -G "Visual Studio 17 2022" -A x64 + +# 构建测试 +cmake --build . --config Debug --target xcengine_math_tests +``` + +### 8.2 运行测试 + +```bash +# 运行所有测试 +ctest --output-on-failure + +# 运行 Math 测试 +./tests/xcengine_math_tests.exe + +# 运行特定测试 +./tests/xcengine_math_tests.exe --gtest_filter=Math_Vector3.* + +# 运行测试并显示详细信息 +./tests/xcengine_math_tests.exe --gtest_also_run_disabled_tests --gtest_print_time=1 +``` + +### 8.3 测试过滤器 + +```bash +# 运行所有 Vector3 测试 +--gtest_filter=Math_Vector3.* + +# 运行除某测试外的所有测试 +--gtest_filter=-Math_Matrix4.SingularMatrix* + +# 运行多个测试 +--gtest_filter=Math_Vector3.*:Math_Matrix4.* +``` + +--- + +## 9. 覆盖率要求 + +| 模块 | 最低覆盖率 | 关键测试 | +|------|-----------|---------| +| Math | 90% | 所有公开 API | +| Core | 80% | 智能指针、Event | +| Containers | 85% | 边界、迭代器 | +| Memory | 90% | 分配/泄漏 | +| Threading | 70% | 基本功能 | + +--- + +## 10. 持续集成 + +```yaml +# .github/workflows/test.yml +name: Test + +on: [push, pull_request] + +jobs: + test: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v3 + + - name: Configure + run: cmake -B build -DENABLE_COVERAGE=ON + + - name: Build + run: cmake --build build --config Debug + + - name: Test + run: ctest --test-dir build --output-on-failure + + - name: Coverage + run: cmake --build build --target coverage +``` + +--- + +## 11. 注意事项 + +1. **浮点数比较** - 必须使用容差 (通常 1e-5 或 1e-6) +2. **边界条件** - 必须测试零向量、奇异矩阵等 +3. **随机性** - 如需固定 seed 保证确定性 +4. **线程安全** - 线程测试需设置超时 +5. **内存泄漏** - 使用 Valgrind 或 CRT 检测 diff --git a/docs/plan/Unity SRP API参考文档.md b/docs/plan/Unity SRP API参考文档.md new file mode 100644 index 0000000..a4cc08f --- /dev/null +++ b/docs/plan/Unity SRP API参考文档.md @@ -0,0 +1,621 @@ +# Unity SRP (Scriptable Render Pipeline) API 参考文档 + +## 1. 概述 + +Unity 的可编写脚本渲染管线 (Scriptable Render Pipeline, SRP) 是一项允许通过 C# 脚本控制渲染的功能。SRP 是通用渲染管线 (URP) 和高清渲染管线 (HDRP) 的底层技术基础。 + +**命名空间**: `UnityEngine.Rendering` + +--- + +## 2. 核心类 API + +### 2.1 RenderPipeline 类 + +**命名空间**: `UnityEngine.Rendering` + +**描述**: 提供实现可编写脚本渲染管线的渲染逻辑的方式。继承自此类以重写 `Render` 方法来实现自定义 SRP。 + +**示例代码**: +```csharp +using UnityEngine; +using UnityEngine.Rendering; +using System.Collections.Generic; + +public class CustomRenderPipeline : RenderPipeline +{ + protected override void Render(ScriptableRenderContext context, List cameras) + { + // 实现自定义 SRP 渲染逻辑 + } +} +``` + +**属性**: +| 属性 | 描述 | +|------|------| +| `disposed` | 返回 true 表示 RenderPipeline 无效或已销毁 | + +**受保护的方法**: +| 方法 | 描述 | +|------|------| +| `IsPreviewSupported()` | 指定相机是否可以预览 | +| `IsRenderRequestSupported()` | 实现此方法以指定特定的相机和渲染请求组合是否受支持 | +| `ProcessRenderRequests()` | 执行使用 RenderPipeline.SubmitRenderRequest 提交的渲染请求 | +| `Render()` | 定义此 RenderPipeline 自定义渲染的入口点方法 | + +**静态方法**: +| 方法 | 描述 | +|------|------| +| `BeginCameraRendering(ScriptableRenderContext, Camera)` | 调用 RenderPipelineManager.beginCameraRendering 委托 | +| `BeginContextRendering(ScriptableRenderContext, List)` | 调用 RenderPipelineManager.beginContextRendering 和 beginFrameRendering 委托 | +| `BeginFrameRendering(ScriptableRenderContext, List)` | 调用 RenderPipelineManager.beginFrameRendering 委托 | +| `EndCameraRendering(ScriptableRenderContext, Camera)` | 调用 RenderPipelineManager.endCameraRendering 委托 | +| `EndContextRendering(ScriptableRenderContext, List)` | 调用 RenderPipelineManager.endContextRendering 和 endFrameRendering 委托 | +| `EndFrameRendering(ScriptableRenderContext, List)` | 调用 RenderPipelineManager.endFrameRendering 委托 | +| `SubmitRenderRequest(Camera, RenderRequest)` | 向相机提交渲染请求(在 Unity 渲染循环之外) | +| `SupportsRenderRequest(Camera, RequestData)` | 检查渲染管线是否支持使用相机的 RequestData 类型 | +| `ProcessRenderRequests(List)` | 执行使用 Camera.SubmitRenderRequest 提交的渲染请求 | + +--- + +### 2.2 RenderPipelineAsset 类 + +**命名空间**: `UnityEngine.Rendering` + +**继承**: `ScriptableObject` + +**描述**: 生成特定 IRenderPipeline 的资源。IRenderPipelineAsset 的默认实现。管理继承类型的生命周期,并确保创建的 IRenderPipeline 在资源更改时失效。 + +**属性**: +| 属性 | 描述 | +|------|------| +| `autodeskInteractiveMaskedShader` | 获取此管线的默认 Autodesk Interactive 遮罩 Shader | +| `autodeskInteractiveShader` | 获取此管线的默认 Autodesk Interactive Shader | +| `autodeskInteractiveTransparentShader` | 获取此管线的默认 Autodesk Interactive 透明 Shader | +| `default2DMaskMaterial` | 获取 Sprite Masks 使用的默认 2D 遮罩材质 | +| `default2DMaterial` | 返回此管线的默认 2D 材质 | +| `defaultLineMaterial` | 返回此管线的默认线条材质 | +| `defaultMaterial` | 返回此管线的默认材质 | +| `defaultParticleMaterial` | 返回此管线的默认粒子材质 | +| `defaultShader` | 返回此管线的默认 Shader | +| `defaultSpeedTree7Shader` | 返回 SpeedTree v7 Shader | +| `defaultSpeedTree8Shader` | 返回 SpeedTree v8 Shader | +| `defaultSpeedTree9Shader` | 返回 SpeedTree v9 Shader | +| `defaultTerrainMaterial` | 返回此管线的默认地形材质 | +| `defaultUIETC1SupportedMaterial` | 返回默认 UI ETC1 材质 | +| `defaultUIMaterial` | 返回默认 UI 材质 | +| `defaultUIOverdrawMaterial` | 返回默认 UI overdraw 材质 | +| `pipelineType` | 返回与此 RenderPipelineAsset 实例关联的 RenderPipeline 类型 | +| `renderPipelineShaderTag` | 返回此资源描述的渲染管线的 Shader Tag 值 | +| `terrainBrushPassIndex` | 编辑器中地形笔刷的渲染索引 | +| `terrainDetailGrassBillboardShader` | 返回此管线的细节草 Billboard Shader | +| `terrainDetailGrassShader` | 返回此管线的细节草 Shader | +| `terrainDetailLitShader` | 返回此管线的细节光照 Shader | + +**受保护的方法**: +| 方法 | 描述 | +|------|------| +| `CreatePipeline()` | 创建此资源特有的 IRenderPipeline | +| `EnsureGlobalSettings()` | 确保全局设置已准备好并注册到 GraphicsSettings | +| `OnDisable()` | RenderPipelineAsset 的 OnDisable 默认实现 | +| `OnValidate()` | RenderPipelineAsset 的 OnValidate 默认实现 | + +--- + +### 2.3 ScriptableRenderContext 类 + +**命名空间**: `UnityEngine.Rendering` + +**类型**: struct (结构体) + +**描述**: 定义自定义渲染管线使用的状态和绘制命令。当定义自定义 RenderPipeline 时,使用 ScriptableRenderContext 来调度和提交状态更新以及绘制命令到 GPU。 + +**公共方法**: +| 方法 | 描述 | +|------|------| +| `BeginRenderPass(RenderTargetIdentifier, RenderPassAttachment, ClearFlag, Color)` | 调度新渲染 pass 的开始 | +| `BeginScopedRenderPass(...)` | 调度渲染 pass 开始,使用 using 语句会自动调用 EndRenderPass | +| `BeginScopedSubPass(...)` | 调度子 pass 开始,使用 using 语句会自动调用 EndSubPass | +| `BeginSubPass(...)` | 调度子 pass 的开始 | +| `CreateGizmoRendererList(...)` | 创建新的 Gizmo RendererList | +| `CreateRendererList(...)` | 创建新的渲染器 RendererList | +| `CreateShadowRendererList(...)` | 创建新的阴影 RendererList | +| `CreateSkyboxRendererList(...)` | 创建新的天空盒 RendererList | +| `CreateUIOverlayRendererList(...)` | 创建新的 UIOverlay RendererList | +| `CreateWireOverlayRendererList(...)` | 创建新的线框覆盖层 RendererList | +| `Cull(ScriptableCullingParameters)` | 执行基于 ScriptableCullingParameters 的剔除 | +| `CullShadowCasters(...)` | 对所有可见光源执行阴影投射体剔除 | +| `DrawGizmos(Camera, GizmoSubset)` | 调度绘制 Gizmos 子集 | +| `DrawUIOverlay(Camera)` | 绘制 UI 覆盖层 | +| `DrawWireOverlay(Camera)` | 调度线框覆盖层绘制 | +| `EndRenderPass()` | 调度当前活动渲染 pass 的结束 | +| `EndSubPass()` | 调度当前活动子 pass 的结束 | +| `ExecuteCommandBuffer(CommandBuffer)` | 调度自定义图形 CommandBuffer 的执行 | +| `ExecuteCommandBufferAsync(CommandBuffer, ComputeQueueType)` | 在异步计算队列上执行 CommandBuffer | +| `HasInvokeOnRenderObjectCallbacks()` | 检查场景中是否有注册 OnRenderObject 回调的对象 | +| `InvokeOnRenderObjectCallback(Camera)` | 调度 MonoBehaviour 脚本的 OnRenderObject 回调执行 | +| `PrepareRendererListsAsync(List)` | 启动在后台处理提供的 RendererLists | +| `QueryRendererListStatus(RendererList)` | 查询 RendererList 的状态 | +| `SetupCameraProperties(Camera)` | 调度相机特定全局 Shader 变量的设置 | +| `StartMultiEye(Camera)` | 调度在 ScriptableRenderContext 上开始细粒度立体渲染 | +| `StopMultiEye(Camera)` | 调度停止立体渲染 | +| `StereoEndRender(Camera)` | 调度单帧立体渲染完成通知 | +| `Submit()` | 提交所有调度的命令到渲染循环执行 | +| `SubmitForRenderPassValidation()` | 验证渲染 pass 是否可以执行调度的命令 | + +**静态方法**: +| 方法 | 描述 | +|------|------| +| `EmitGeometryForCamera(Camera)` | 为指定相机发射 UI 几何体进行渲染 | +| `EmitWorldGeometryForSceneView(SceneView)` | 为场景视图发射 UI 几何体 | +| `PopDisableApiRenderers()` | 启用渲染器场景节点的即时添加和移除 | +| `PushDisableApiRenderers()` | 阻止渲染器场景节点的即时添加或移除 | + +--- + +### 2.4 ScriptableRenderPass 类 + +**命名空间**: `UnityEngine.Rendering` + +**描述**: 可编写脚本的渲染 Pass 基类。用于实现自定义渲染 passes。 + +**主要成员**: +| 成员 | 描述 | +|------|------| +| `renderPassEvent` | 指定 Pass 在渲染管线中的执行时机 | +| `ConfigureInput()` | 配置渲染器输入 | +| `ConfigureTarget()` | 配置渲染目标 | +| `Execute()` | 执行 Pass 的渲染逻辑 | +| `FrameCleanup()` | 帧清理回调 | +| `OnCameraSetup()` | 相机设置回调 | +| `OnCameraCleanup()` | 相机清理回调 | + +--- + +### 2.5 ScriptableRenderer 类 + +**命名空间**: `UnityEngine.Rendering` + +**描述**: 可编写脚本的渲染器实现基类。 + +**主要方法**: +| 方法 | 描述 | +|------|------| +| `EnqueuePass(ScriptableRenderPass)` | 将渲染 Pass 加入队列 | +| `Execute(ScriptableRenderContext, ref RenderingData)` | 执行渲染 | +| `Initialize()` | 初始化渲染器 | +| `Submit()` | 提交渲染 | +| `ConfigureCameraTarget(RenderTargetIdentifier, RenderTargetIdentifier)` | 配置相机渲染目标 | +| `ConfigureColorStoreAction(RenderTargetStoreAction)` | 配置颜色存储操作 | +| `ConfigureDepthStoreAction(RenderTargetStoreAction)` | 配置深度存储操作 | + +**属性**: +| 属性 | 描述 | +|------|------| +| `supportedRenderingFeatures` | 支持的渲染特性 | +| `rendererFeatures` | 渲染器特性列表 | +| `krenderGraphResourceSet` | 渲染图资源集 | + +--- + +### 2.6 RenderPassEvent 枚举 + +**命名空间**: `UnityEngine.Rendering` + +**描述**: 指定渲染 Pass 在渲染管线中的执行时机。 + +**枚举值**: +| 值 | 描述 | +|------|------| +| `BeforeRendering` | 渲染开始前 | +| `BeforeRenderingShadows` | 阴影渲染前 | +| `BeforeRenderingPrePasses` | 预 Pass (如深度预通道) 前 | +| `BeforeRenderingOpaques` | 不透明物体渲染前 | +| `BeforeRenderingGbuffer` | G-Buffer (延迟渲染) 前 | +| `BeforeRenderingLit` | 光照物体前 | +| `BeforeRenderingTransparents` | 透明物体渲染前 | +| `BeforeRenderingOverlays` | 覆盖层 (如 UI) 前 | +| `BeforeAlphaMask` | Alpha 遮罩前 | +| `AfterRendering` | 渲染结束后 | +| `AfterRenderingShadows` | 阴影渲染后 | +| `AfterRenderingPrePasses` | 预 Pass 后 | +| `AfterRenderingOpaques` | 不透明物体渲染后 | +| `AfterRenderingGbuffer` | G-Buffer 后 | +| `AfterRenderingLit` | 光照物体后 | +| `AfterRenderingTransparents` | 透明物体渲染后 | +| `AfterRenderingOverlays` | 覆盖层后 | +| `AfterAlphaMask` | Alpha 遮罩后 | + +--- + +### 2.7 CullingResults 类 + +**命名空间**: `UnityEngine.Rendering` + +**描述**: 包含剔除操作的结果,用于渲染对象和光源。 + +**主要方法**: +| 方法 | 描述 | +|------|------| +| `FillLightAndReflectionProbeIndices(...)` | 填充光照和反射探针索引 | +| `GetLightIndexMap()` | 获取光照索引映射 | +| `GetReflectionProbeIndexMap()` | 获取反射探针索引映射 | +| `SetLightIndexMap(int[], int[])` | 设置光照索引映射 | + +**属性**: +| 属性 | 描述 | +|------|------| +| `visibleLights` | 可见光源列表 | +| `visibleReflectionProbes` | 可见反射探针列表 | +| `lightAndReflectionProbeIndex` | 光照和反射探针索引数据 | + +--- + +### 2.8 ScriptableCullingParameters 结构体 + +**命名空间**: `UnityEngine.Rendering` + +**描述**: 包含用于剔除操作的参数。 + +**主要成员**: +| 成员 | 描述 | +|------|------| +| `camera` | 剔除相机 | +| `cullingPlaneSet` | 剔除平面集 | +| `cullingMask` | 剔除遮罩 | +| `lightCullingMode` | 光照剔除模式 | +| `reflectionProbeCullingMode` | 反射探针剔除模式 | +| `shadowDistance` | 阴影距离 | +| `shadowNearPlane` | 阴影近平面 | +| `maximumPortalCullingJobs` | 最大门户剔除作业数 | + +**静态方法**: +| 方法 | 描述 | +|------|------| +| `GetCullingParameters(Camera, ScriptableCullingParameters)` | 从相机获取剔除参数 | +| `GetCullingParametersForEditor(Camera, ScriptableCullingParameters)` | 为编辑器获取剔除参数 | + +--- + +## 3. CommandBuffer 相关 API + +### 3.1 CommandBuffer 类 + +**命名空间**: `UnityEngine.Rendering` + +**描述**: 用于存储渲染命令的缓冲区。 + +**常用方法**: +| 方法 | 描述 | +|------|------| +| `Blit()` | 执行纹理拷贝 (blit) 操作 | +| `DrawRenderer()` | 绘制渲染器 | +| `DrawMesh()` | 绘制网格 | +| `DrawMeshInstanced()` | 绘制实例化网格 | +| `SetRenderTarget()` | 设置渲染目标 | +| `SetGlobalTexture()` | 设置全局纹理 | +| `SetGlobalFloat()` | 设置全局浮点数 | +| `SetGlobalVector()` | 设置全局向量 | +| `SetGlobalMatrix()` | 设置全局矩阵 | +| `SetViewProjectionMatrices()` | 设置视图投影矩阵 | +| `ClearRenderTarget()` | 清除渲染目标 | +| `CopyTexture()` | 复制纹理 | +| `ComputeDispatch()` | 计算着色器调度 | + +### 3.2 CommandBufferPool 类 + +**命名空间**: `UnityEngine.Rendering` + +**描述**: CommandBuffer 池化管理器,用于优化内存分配。 + +**静态方法**: +| 方法 | 描述 | +|------|------| +| `Get(string)` | 从池中获取 CommandBuffer | +| `Release(CommandBuffer)` | 释放 CommandBuffer 回池 | +| `Create(string)` | 创建新的 CommandBuffer | +| `ReleaseAll()` | 释放所有池化的 CommandBuffer | + +### 3.3 RenderingData 结构体 + +**命名空间**: `UnityEngine.Rendering` + +**描述**: 包含传递给 ScriptableRenderPass.Execute 的渲染数据。 + +**属性**: +| 属性 | 描述 | +|------|------| +| `cameraData` | 相机数据 | +| `cullingResults` | 剔除结果 | +| `lightData` | 光照数据 | +| `shadowData` | 阴影数据 | + +### 3.4 CameraData 结构体 + +**命名空间**: `UnityEngine.Rendering` + +**描述**: 包含相机相关的渲染数据。 + +**属性**: +| 属性 | 描述 | +|------|------| +| `camera` | Unity Camera 对象 | +| `projectionMatrix` | 投影矩阵 | +| `viewMatrix` | 视图矩阵 | +| `renderer` | 渲染器 | + +--- + +## 4. 渲染相关类 + +### 4.1 ShaderTagId + +**命名空间**: `UnityEngine.Rendering` + +**描述**: Shader 标签标识符,用于标识 Shader 的渲染通道。 + +### 4.2 LightProbe + +**命名空间**: `UnityEngine.Rendering` + +**描述**: 光照探针管理类,用于处理光照探针数据。 + +### 4.3 DrawRendererSettings + +**命名空间**: `UnityEngine.Rendering` + +**描述**: 渲染器绘制设置结构体,用于配置渲染器绘制参数。 + +**主要成员**: +| 成员 | 描述 | +|------|------| +| `sorting` | 排序设置 | +| `flags` | 渲染标志 | +| `rendererConfiguration` | 渲染器配置 | +| `passIndex` | Pass 索引 | + +--- + +## 5. URP (Universal Render Pipeline) 核心 API + +**包**: `com.unity.render-pipelines.universal` + +**命名空间**: `UnityEngine.Rendering.Universal` + +URP 是建立在 SRP Core 之上的渲染管线,提供了更简化的 API。 + +### 5.1 UniversalRenderPipeline 类 + +**命名空间**: `UnityEngine.Rendering.Universal` + +**描述**: URP 的主渲染管线类。 + +**属性**: +| 属性 | 描述 | +|------|------| +| `asset` | 当前 URP 资源 | +| `current` | 当前活动的渲染管线 | + +### 5.2 UniversalRenderPipelineAsset 类 + +**命名空间**: `UnityEngine.Rendering.Universal` + +**描述**: URP 的渲染管线资源资产。 + +### 5.3 ForwardRenderer 类 + +**命名空间**: `UnityEngine.Rendering.Universal` + +**描述**: URP 的前向渲染器实现。 + +### 5.4 RenderingData (URP扩展) + +URP 扩展了基础的 RenderingData,添加了 URP 特有的渲染数据。 + +### 5.5 URP 核心 Pass 类 + +| 类名 | 描述 | +|------|------| +| `ScriptableRenderPass` | URP 中继承自基类的渲染 Pass | +| `ScriptableBlitPass` | Blit 渲染 Pass | +| `ScriptableFullscreenPass` | 全屏渲染 Pass | +| `ColorGradingLutPass` | 颜色分级 LUT Pass | +| `BloomPass` | 泛光 Pass | +| `DepthOfFieldPass` | 景深 Pass | +| `MotionVectorPass` | 运动矢量 Pass | + +### 5.6 RenderPassEvent (URP扩展) + +URP 扩展了标准的 RenderPassEvent,添加了 URP 特有的渲染事件。 + +--- + +## 6. HDRP (High Definition Render Pipeline) 核心 API + +**包**: `com.unity.render-pipelines.high-definition` + +**命名空间**: `UnityEngine.Rendering.HighDefinition` + +HDRP 是建立在 SRP Core 之上的高端渲染管线,提供了高质量的渲染效果。 + +### 6.1 HDRenderPipeline 类 + +**命名空间**: `UnityEngine.Rendering.HighDefinition` + +**描述**: HDRP 的主渲染管线类。 + +### 6.2 HDRenderPipelineAsset 类 + +**命名空间**: `UnityEngine.Rendering.HighDefinition` + +**描述**: HDRP 的渲染管线资源资产。 + +### 6.3 HDRenderer 类 + +**命名空间**: `UnityEngine.Rendering.HighDefinition` + +**描述**: HDRP 的渲染器实现。 + +### 6.4 HDRP 核心组件 + +| 类名 | 描述 | +|------|------| +| `HDRenderPipelineAsset` | HDRP 资源资产 | +| `HDRenderer` | HDRP 渲染器 | +| `HDBaker` | 光照烘焙器 | +| `RayTracingShader` | 光线追踪着色器 | + +### 6.5 HDRP 专用 Pass + +| Pass 类 | 描述 | +|---------|------| +| `DeferredPass` | 延迟渲染 Pass | +| `ForwardEmissivePass` | 前向发光 Pass | +| `TransparentDepthPrePass` | 透明物体深度预 Pass | +| `MotionVectorPass` | 运动矢量 Pass | + +--- + +## 7. SRP Core 核心类 (com.unity.render-pipelines.core) + +### 7.1 核心工具类 + +| 类名 | 描述 | +|------|------| +| `CoreUtils` | SRP 核心工具函数集合 | +| `CoreMatrixUtils` | 矩阵操作工具函数 | +| `Blitter` | Blit (纹理拷贝) 工具 | +| `RTHandle` | 可自动缩放的渲染纹理 | +| `RTHandleSystem` | RTHandle 纹理管理系统 | +| `Volume` | 通用 Volume 组件 | +| `VolumeManager` | Volume 全局管理器 | +| `VolumeProfile` | Volume 设置资源 | +| `VolumeComponent` | Volume 组件基类 | + +### 7.2 调试相关类 + +| 类名 | 描述 | +|------|------| +| `DebugManager` | 调试窗口管理器 | +| `DebugUI` | 调试 UI 类 | +| `DebugUI.Widget` | 调试 UI 组件基类 | +| `ProfilingSampler` | CPU/GPU 性能分析采样器 | +| `ProfilingScope` | 性能分析作用域 | +| `Recorder` | 性能记录器 | +| `Profiler` | 性能分析器 | + +### 7.3 资源管理类 + +| 类名 | 描述 | +|------|------| +| `RenderPipelineGlobalSettings` | 渲染管线全局设置 | +| `RenderPipelineResources` | 渲染管线资源资产基类 | +| `ConstantBuffer` | 常量缓冲区管理 | +| `ShaderVariation` | Shader 变体管理 | +| `MaterialDescription` | 材质描述 | + +### 7.4 渲染 Pass 基类 + +| 类名 | 描述 | +|------|------| +| `ScriptableRenderPass` | 可编写脚本的渲染 Pass 基类 | +| `ScriptableBlitPass` | Blit 操作 Pass 基类 | +| `ScriptableCopyPass` | 拷贝 Pass 基类 | + +### 7.5 渲染器特性 + +| 类名 | 描述 | +|------|------| +| `RenderingFeatures` | 渲染特性集合 | +| `RendererFeatures` | 渲染器特性集合 | +| `RenderPipelineFeature` | 渲染管线特性基类 | + +--- + +## 8. 使用示例 + +### 8.1 创建自定义渲染管线 + +```csharp +using UnityEngine; +using UnityEngine.Rendering; +using System.Collections.Generic; + +public class CustomRenderPipeline : RenderPipeline +{ + protected override void Render(ScriptableRenderContext context, List cameras) + { + foreach (var camera in cameras) + { + // 渲染每个相机 + Render(context, camera); + } + + // 提交渲染命令 + context.Submit(); + } + + private void Render(ScriptableRenderContext context, Camera camera) + { + // 设置相机属性 + context.SetupCameraProperties(camera); + + // 创建命令缓冲区 + CommandBuffer cmd = CommandBufferPool.Get("Clear"); + cmd.ClearRenderTarget(true, true, Color.black); + context.ExecuteCommandBuffer(cmd); + CommandBufferPool.Release(cmd); + + // 提交 + context.Submit(); + } +} +``` + +### 8.2 创建自定义渲染 Pass + +```csharp +using UnityEngine; +using UnityEngine.Rendering; + +public class CustomRenderPass : ScriptableRenderPass +{ + public CustomRenderPass() + { + // 设置 Pass 执行时机 + renderPassEvent = RenderPassEvent.BeforeRenderingOpaques; + } + + public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) + { + // 相机设置 + } + + public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) + { + // 执行渲染逻辑 + } + + public override void FrameCleanup(CommandBuffer cmd) + { + // 帧清理 + } +} +``` + +--- + +## 9. 官方文档资源 + +- [SRP 官方文档](https://docs.unity3d.com/Manual/ScriptableRenderPipeline.html) +- [URP Scripting API](https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@latest/api/) +- [HDRP Scripting API](https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@latest/api/) +- [SRP Core Scripting API](https://docs.unity3d.com/Packages/com.unity.render-pipelines.core@latest/api/) + +--- + +*文档版本: 1.1* +*更新日期: 2026-03-16* +*Unity 版本: 6.3 LTS (6000.3)* +*基于官方 Unity API 文档调研整理* diff --git a/docs/plan/XCEngine渲染引擎架构设计.md b/docs/plan/XCEngine渲染引擎架构设计.md new file mode 100644 index 0000000..faff46f --- /dev/null +++ b/docs/plan/XCEngine渲染引擎架构设计.md @@ -0,0 +1,4564 @@ +# XCEngine - 渲染引擎架构设计文档 + +> **借鉴 Unity 渲染架构概念设计** + +--- + +## 渲染流程图 + +``` +┌─────────────────────────────────────────────────────────────────────────────────────┐ +│ 渲染流程 │ +└─────────────────────────────────────────────────────────────────────────────────────┘ + +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ +│ Scene │────▶│ Culling │────▶│ RenderQueue │────▶│ Renderer │ +│ 场景数据 │ │ System │ │ 渲染队列 │ │ 渲染器 │ +└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ + │ │ │ + ▼ │ ▼ + ┌─────────────┐ │ ┌─────────────┐ + │CullingResults│◀──────────┘ │ CommandList │ + │ 剔除结果 │ PrepareRender │ 命令列表 │ + └─────────────┘ QueueEntries └─────────────┘ + │ + ▼ +┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ +│ Camera │────▶│ LightManager│────▶│ Pass │────▶│ GPU │ +│ 相机 │ │ 光照管理 │ │ 渲染通道 │ │ GPU执行 │ +└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ + │ │ + ▼ ▼ + ┌─────────────┐ ┌─────────────┐ + │ ShadowAtlas │ │ Material │ + │ 阴影图集 │ │ 材质 │ + └─────────────┘ └─────────────┘ + +流程说明: +1. Scene 提供场景数据(GameObjects, Components) +2. CullingSystem 执行视锥剔除,产出 CullingResults +3. RenderQueue 根据 CullingResults 准备渲染项(Renderer::PrepareRenderQueueEntries) +4. Renderer 遍历 RenderQueue,通过 CommandList 提交绘制命令 +5. LightManager/ShadowAtlas 处理光照和阴影 +6. 最终 GPU 执行渲染命令 +``` + +``` +┌─────────────────────────────────────────────────────────────────────────────────────┐ +│ RHI 抽象层架构 │ +└─────────────────────────────────────────────────────────────────────────────────────┘ + + ┌─────────────────┐ + │ RHISystem │ 渲染系统入口 + └────────┬────────┘ + │ + ┌───────────────────────┼───────────────────────┐ + │ │ │ + ┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐ + │ D3D12Device │ │ D3D11Device │ │ VulkanDevice │ + └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ + │ │ │ + └───────────────────────┼───────────────────────┘ + │ + ┌────────▼────────┐ + │ IRHIDevice │ 抽象设备接口 + └────────┬────────┘ + │ + ┌──────────────────────────────────┼──────────────────────────────────┐ + │ │ │ │ │ │ │ + ┌────▼────┐ ┌───▼────┐ ┌────▼┐ ┌──▼────┐ ┌───▼───┐ ┌───▼────┐ ┌──▼────┐ + │CommandQueue│ │Descriptor│ │Fence│ │SwapChain│ │RootSig│ │PSO │ │Texture│ + │ 命令队列 │ │Heap │ │围栏 │ │交换链 │ │根签名 │ │管线状态│ │纹理 │ + └──────────┘ └────────┘ └─────┘ └────────┘ └───────┘ └───────┘ └───────┘ +``` + +> **重要声明**:本架构借鉴 Unity 渲染系统的核心概念与设计模式,包括: +> - `CullingResults` / `CullingSystem` - 剔除系统(概念来自Unity SRP API) +> - `RenderPipeline` / `RenderPipelineManager` - 渲染管线 +> - `RenderQueue` / `RenderQueueEntry` - 渲染队列 +> - `Renderer` - 渲染器核心 +> - `ScriptableRenderContext` - 渲染上下文 +> - `Shader` / `Pass` / `Material` - 着色器与材质 +> - `LightManager` / `ShadowAtlas` - 光照与阴影管理 +> +> **注**:Unity底层C++渲染架构未公开,本设计基于公开API概念与通用渲染引擎模式实现。 +> +> 版本: 1.0 +> 日期: 2026-03-13 +> 目标: 构建专业级实时体积渲染引擎 + +--- + +## 第一章 核心基础层 + +### 1.1 数学库 (Math Library) + +```cpp +namespace XCEngine { +namespace Math { + +struct Vector2 { + float x, y; + + static Vector2 Zero() { return Vector2{0, 0}; } + static Vector2 One() { return Vector2{1, 1}; } + static Vector2 Up() { return Vector2{0, 1}; } + static Vector2 Down() { return Vector2{0, -1}; } + static Vector2 Right() { return Vector2{1, 0}; } + static Vector2 Left() { return Vector2{-1, 0}; } + + static float Dot(const Vector2& a, const Vector2& b); + static float Cross(const Vector2& a, const Vector2& b); + static Vector2 Normalize(const Vector2& v); + static float Magnitude(const Vector2& v); + static Vector2 Lerp(const Vector2& a, const Vector2& b, float t); +}; + +struct Vector3 { + float x, y, z; + + static Vector3 Zero() { return Vector3{0, 0, 0}; } + static Vector3 One() { return Vector3{1, 1, 1}; } + static Vector3 Forward() { return Vector3{0, 0, 1}; } + static Vector3 Back() { return Vector3{0, 0, -1}; } + static Vector3 Up() { return Vector3{0, 1, 0}; } + static Vector3 Down() { return Vector3{0, -1, 0}; } + static Vector3 Right() { return Vector3{1, 0, 0}; } + static Vector3 Left() { return Vector3{-1, 0, 0}; } + + static Vector3 Cross(const Vector3& a, const Vector3& b); + static float Dot(const Vector3& a, const Vector3& b); + static Vector3 Normalize(const Vector3& v); + static float Magnitude(const Vector3& v); + static float SqrMagnitude(const Vector3& v); + static Vector3 Lerp(const Vector3& a, const Vector3& b, float t); + static Vector3 MoveTowards(const Vector3& current, const Vector3& target, float maxDistance); +}; + +struct Vector4 { float x, y, z, w; }; + +struct Matrix3x3 { + float m[3][3]; + + static Matrix3x3 Identity() { + Matrix3x3 result{}; + result.m[0][0] = 1.0f; result.m[1][1] = 1.0f; result.m[2][2] = 1.0f; + return result; + } + + static Matrix3x3 Zero() { + Matrix3x3 result{}; + return result; + } + + Matrix3x3 operator*(const Matrix3x3& other) const; + Vector3 operator*(const Vector3& v) const; + Matrix3x3 Transpose() const; + Matrix3x3 Inverse() const; + float Determinant() const; +}; + +struct Matrix4x4 { + float m[4][4]; + + static Matrix4x4 Identity() { + Matrix4x4 result{}; + result.m[0][0] = 1.0f; result.m[1][1] = 1.0f; + result.m[2][2] = 1.0f; result.m[3][3] = 1.0f; + return result; + } + + static Matrix4x4 Zero() { + Matrix4x4 result{}; + return result; + } + + static Matrix4x4 Translation(const Vector3& v); + static Matrix4x4 Rotation(const Quaternion& q); + static Matrix4x4 Scale(const Vector3& v); + static Matrix4x4 TRS(const Vector3& translation, const Quaternion& rotation, const Vector3& scale); + static Matrix4x4 LookAt(const Vector3& eye, const Vector3& target, const Vector3& up); + static Matrix4x4 Perspective(float fov, float aspect, float near, float far); + static Matrix4x4 Orthographic(float left, float right, float bottom, float top, float near, float far); + + Matrix4x4 operator*(const Matrix4x4& other) const; + Vector4 operator*(const Vector4& v) const; + Vector3 MultiplyPoint(const Vector3& v) const; + Vector3 MultiplyVector(const Vector3& v) const; + + Matrix4x4 Transpose() const; + Matrix4x4 Inverse() const; + float Determinant() const; + + Vector3 GetTranslation() const; + Quaternion GetRotation() const; + Vector3 GetScale() const; + + void Decompose(Vector3& translation, Quaternion& rotation, Vector3& scale) const; +}; + +struct Quaternion { + float x, y, z, w; + + static Quaternion Identity() { return Quaternion{0, 0, 0, 1}; } + + static Quaternion FromAxisAngle(const Vector3& axis, float radians); + static Quaternion FromEulerAngles(float pitch, float yaw, float roll); + static Quaternion FromRotationMatrix(const Matrix4x4& matrix); + static Quaternion Slerp(const Quaternion& a, const Quaternion& b, float t); + static Quaternion LookRotation(const Vector3& forward, const Vector3& up = Vector3::Up()); + + Vector3 ToEulerAngles() const; + Matrix4x4 ToMatrix4x4() const; + Vector3 operator*(const Vector3& v) const; + + Quaternion operator*(const Quaternion& other) const; + Quaternion Inverse() const; + float Dot(const Quaternion& other) const; +}; + +struct Transform { + Vector3 position = Vector3::Zero(); + Quaternion rotation = Quaternion::Identity(); + Vector3 scale = Vector3::One(); + + Matrix4x4 ToMatrix() const; + Transform Inverse() const; + Transform operator*(const Transform& other) const; + Vector3 TransformPoint(const Vector3& point) const; + Vector3 TransformDirection(const Vector3& direction) const; +}; + +enum class Space { + Self, + World +}; + +struct Color { + float r, g, b, a; + + static Color White() { return Color{1, 1, 1, 1}; } + static Color Black() { return Color{0, 0, 0, 1}; } + static Color Red() { return Color{1, 0, 0, 1}; } + static Color Green() { return Color{0, 1, 0, 1}; } + static Color Blue() { return Color{0, 0, 1, 1}; } + static Color Yellow() { return Color{1, 1, 0, 1}; } + static Color Cyan() { return Color{0, 1, 1, 1}; } + static Color Magenta() { return Color{1, 0, 1, 1}; } + static Color Clear() { return Color{0, 0, 0, 0}; } + + static Color Lerp(const Color& a, const Color& b, float t); +}; + +struct Rect { + float x, y, width, height; + + Rect() : x(0), y(0), width(0), height(0) {} + Rect(float x, float y, float w, float h) : x(x), y(y), width(w), height(h) {} + + float GetLeft() const { return x; } + float GetRight() const { return x + width; } + float GetTop() const { return y; } + float GetBottom() const { return y + height; } + + Vector2 GetPosition() const { return Vector2{x, y}; } + Vector2 GetSize() const { return Vector2{width, height}; } + + bool Contains(float px, float py) const { + return px >= x && px < x + width && py >= y && py < y + height; + } +}; + +struct RectInt { + int32_t x, y, width, height; + + RectInt() : x(0), y(0), width(0), height(0) {} + RectInt(int32_t x, int32_t y, int32_t w, int32_t h) : x(x), y(y), width(w), height(h) {} +}; + +struct Viewport { + float x, y, width, height; + float minDepth = 0.0f; + float maxDepth = 1.0f; + + Viewport() : x(0), y(0), width(0), height(0) {} + Viewport(float x, float y, float w, float h) : x(x), y(y), width(w), height(h) {} +}; + +struct Ray { + Vector3 origin; + Vector3 direction; + + Vector3 GetPoint(float t) const; + bool Intersects(const Sphere& sphere, float& t) const; + bool Intersects(const Box& box, float& t) const; + bool Intersects(const Plane& plane, float& t) const; +}; + +struct Sphere { Vector3 center; float radius; }; +struct Box { Vector3 center; Vector3 extents; Matrix4x4 transform; }; +struct Plane { Vector3 normal; float distance; }; +struct Frustum; +struct OBB; +struct AABB; + +} // namespace Math +} // namespace XCEngine +``` + +### 1.2 内存管理 (Memory Management) + +```cpp +namespace XCEngine { +namespace Memory { + +class IAllocator { +public: + virtual ~IAllocator() = default; + + virtual void* Allocate(size_t size, size_t alignment = 0) = 0; + virtual void Free(void* ptr) = 0; + virtual void* Reallocate(void* ptr, size_t newSize) = 0; + + virtual size_t GetTotalAllocated() const = 0; + virtual size_t GetTotalFreed() const = 0; + virtual size_t GetPeakAllocated() const = 0; + virtual size_t GetAllocationCount() const = 0; + + virtual const char* GetName() const = 0; +}; + +class LinearAllocator : public IAllocator { +public: + explicit LinearAllocator(size_t size, IAllocator* parent = nullptr); + ~LinearAllocator(); + + void* Allocate(size_t size, size_t alignment = 8) override; + void Free(void* ptr) override; + void Clear(); + + void* GetMarker() const; + void SetMarker(void* marker); + +private: + byte* m_buffer = nullptr; + size_t m_capacity = 0; + size_t m_offset = 0; + IAllocator* m_parent = nullptr; +}; + +class PoolAllocator : public IAllocator { +public: + PoolAllocator(size_t blockSize, size_t poolSize, size_t alignment = 8); + ~PoolAllocator(); + + void* Allocate(size_t size, size_t alignment = 0) override; + void Free(void* ptr) override; + + bool Contains(void* ptr) const; + size_t GetBlockSize() const { return m_blockSize; } + size_t GetFreeBlockCount() const; + +private: + struct FreeNode { + FreeNode* next; + }; + + size_t m_blockSize = 0; + size_t m_alignment = 0; + void* m_memory = nullptr; + FreeNode* m_freeList = nullptr; + size_t m_totalBlocks = 0; + size_t m_freeBlocks = 0; +}; + +class ProxyAllocator : public IAllocator { +public: + ProxyAllocator(IAllocator* underlying, const char* name); + + void* Allocate(size_t size, size_t alignment = 0) override; + void Free(void* ptr) override; + void* Reallocate(void* ptr, size_t newSize) override; + + struct Stats { + size_t totalAllocated; + size_t totalFreed; + size_t peakAllocated; + size_t allocationCount; + size_t memoryOverhead; + }; + const Stats& GetStats() const; + +private: + IAllocator* m_underlying; + const char* m_name; + Stats m_stats; + Mutex m_mutex; +}; + +class MemoryManager { +public: + static MemoryManager& Get(); + + void Initialize(); + void Shutdown(); + + IAllocator* GetSystemAllocator(); + + std::unique_ptr CreateLinearAllocator(size_t size); + std::unique_ptr CreatePoolAllocator(size_t blockSize, size_t count); + std::unique_ptr CreateProxyAllocator(const char* name); + + void SetTrackAllocations(bool track); + void DumpMemoryLeaks(); + void GenerateMemoryReport(); +}; + +#define XE_ALLOC(allocator, size, ...) allocator->Allocate(size, ##__VA_ARGS__) +#define XE_FREE(allocator, ptr) allocator->Free(ptr) + +} // namespace Memory +} // namespace XCEngine +``` + +### 1.3 容器库 (Containers) + +```cpp +namespace XCEngine { +namespace Containers { + +template +class Array { +public: + using Iterator = T*; + using ConstIterator = const T*; + + Array() = default; + explicit Array(size_t capacity); + Array(size_t count, const T& value); + Array(std::initializer_list init); + ~Array(); + + Array(const Array& other); + Array(Array&& other) noexcept; + Array& operator=(const Array& other); + Array& operator=(Array&& other) noexcept; + + T& operator[](size_t index); + const T& operator[](size_t index) const; + + T* Data() { return m_data; } + const T* Data() const { return m_data; } + + size_t Size() const { return m_size; } + size_t Capacity() const { return m_capacity; } + + void Clear(); + void PushBack(const T& value); + void PushBack(T&& value); + template + T& EmplaceBack(Args&&... args); + void PopBack(); + +private: + T* m_data = nullptr; + size_t m_size = 0; + size_t m_capacity = 0; + IAllocator* m_allocator = nullptr; +}; + +class String { +public: + String(); + String(const char* str); + String(const char* str, size_t len); + ~String(); + + String& operator+=(const String& other); + String& operator+=(const char* str); + + String Substring(size_t pos, size_t len = npos) const; + String Trim() const; + String ToLower() const; + String ToUpper() const; + + size_t Find(const char* str, size_t pos = 0) const; + bool StartsWith(const String& prefix) const; + bool EndsWith(const String& suffix) const; + + const char* CStr() const { return m_data; } + size_t Length() const { return m_length; } + +private: + char* m_data = nullptr; + size_t m_length = 0; + size_t m_capacity = 0; +}; + +template +class HashMap { +public: + struct Pair { + Key first; + Value second; + }; + + HashMap() = default; + explicit HashMap(size_t bucketCount, IAllocator* allocator = nullptr); + + Value& operator[](const Key& key); + Value* Find(const Key& key); + const Value* Find(const Key& key) const; + bool Contains(const Key& key) const; + + bool Insert(const Key& key, const Value& value); + bool Erase(const Key& key); + void Clear(); + + size_t Size() const { return m_size; } + +private: + size_t GetBucketIndex(const Key& key) const; + void Resize(); + + struct Bucket { + Array pairs; + }; + Array m_buckets; + size_t m_bucketCount = 0; + size_t m_size = 0; + float m_loadFactor = 0.75f; + IAllocator* m_allocator = nullptr; +}; + +} // namespace Containers +} // namespace XCEngine +``` + +### 1.4 线程系统 (Threading) + +```cpp +namespace XCEngine { +namespace Threading { + +enum class TaskPriority : uint8_t { + Critical = 0, + High = 1, + Normal = 2, + Low = 3, + Idle = 4 +}; + +enum class TaskStatus : uint8_t { + Pending, + Scheduled, + Running, + Completed, + Failed, + Canceled +}; + +template +using Func = std::function; + +class ITask { +public: + virtual ~ITask() = default; + + virtual void Execute() = 0; + virtual void OnComplete() {} + virtual void OnCancel() {} + + TaskPriority GetPriority() const { return m_priority; } + TaskStatus GetStatus() const { return m_status; } + uint64 GetId() const { return m_id; } + +protected: + TaskPriority m_priority = TaskPriority::Normal; + TaskStatus m_status = TaskStatus::Pending; + uint64 m_id = 0; + std::atomic m_refCount{1}; +}; + +template +class LambdaTask : public ITask { +public: + explicit LambdaTask(Func&& func, TaskPriority priority = TaskPriority::Normal) + : m_func(std::move(func)), m_priority(priority) {} + + void Execute() override { + m_func(); + } + +private: + Func m_func; +}; + +class TaskGroup { +public: + using Callback = std::function; + + TaskGroup(); + ~TaskGroup(); + + uint64 AddTask(std::unique_ptr task); + uint64 AddTask(Func&& func, TaskPriority priority = TaskPriority::Normal); + + void AddDependency(uint64 taskId, uint64 dependsOn); + void Wait(); + bool WaitFor(std::chrono::milliseconds timeout); + + void SetCompleteCallback(Callback&& callback); + bool IsComplete() const; + float GetProgress() const; +}; + +class TaskSystem { +public: + static TaskSystem& Get(); + + void Initialize(const TaskSystemConfig& config); + void Shutdown(); + + uint64 Submit(std::unique_ptr task); + uint64 Submit(Func&& func, TaskPriority priority = TaskPriority::Normal); + + TaskGroup* CreateTaskGroup(); + void DestroyTaskGroup(TaskGroup* group); + + void Wait(uint64 taskId); + uint32 GetWorkerThreadCount() const; + + void Update(); + + template + void ParallelFor(int32 start, int32 end, Func&& func); + + void RunOnMainThread(Func&& func); +}; + +class Mutex { +public: + Mutex() = default; + ~Mutex() = default; + + void Lock(); + void Unlock(); + bool TryLock(); + +private: + std::mutex m_mutex; +}; + +class SpinLock { +public: + void Lock(); + void Unlock(); + bool TryLock(); + +private: + std::atomic_flag m_flag = ATOMIC_FLAG_INIT; +}; + +class ReadWriteLock { +public: + void ReadLock(); + void ReadUnlock(); + void WriteLock(); + void WriteUnlock(); + +private: + std::mutex m_mutex; + std::condition_variable m_readCondition; + std::condition_variable m_writeCondition; + int32_t m_readers = 0; + int32_t m_writersWaiting = 0; + bool m_writerActive = false; +}; + +class Thread { +public: + using Id = uint64_t; + + Thread(); + ~Thread(); + + template + void Start(Func&& func, const String& name = "Thread"); + void Join(); + void Detach(); + + Id GetId() const { return m_id; } + const String& GetName() const { return m_name; } + + static Id GetCurrentId(); + static void Sleep(uint32_t milliseconds); + static void Yield(); + +private: + Id m_id = 0; + String m_name; + std::thread m_thread; +}; + +} // namespace Threading +} // namespace XCEngine +``` + +### 1.5 日志与调试系统 + +```cpp +namespace XCEngine { +namespace Core { + +template +class Event { +public: + using Callback = std::function; + using Listener = std::pair; + using Iterator = typename std::vector::iterator; + + uint64_t Subscribe(Callback callback) { + std::lock_guard lock(m_mutex); + uint64_t id = ++m_nextId; + m_listeners.emplace_back(id, std::move(callback)); + return id; + } + + void Unsubscribe(uint64_t id) { + std::lock_guard lock(m_mutex); + m_pendingUnsubscribes.push_back(id); + } + + void ProcessUnsubscribes() { + std::lock_guard lock(m_mutex); + for (uint64_t id : m_pendingUnsubscribes) { + m_listeners.erase( + std::remove_if(m_listeners.begin(), m_listeners.end(), + [id](const auto& pair) { return pair.first == id; }), + m_listeners.end() + ); + } + m_pendingUnsubscribes.clear(); + } + + void Invoke(Args... args) const { + std::vector listenersCopy; + { + std::lock_guard lock(m_mutex); + if (!m_pendingUnsubscribes.empty()) { + for (uint64_t id : m_pendingUnsubscribes) { + m_listeners.erase( + std::remove_if(m_listeners.begin(), m_listeners.end(), + [id](const auto& pair) { return pair.first == id; }), + m_listeners.end() + ); + } + m_pendingUnsubscribes.clear(); + } + listenersCopy = m_listeners; + } + for (const auto& [id, callback] : listenersCopy) { + callback(args...); + } + } + + void Clear() { + std::lock_guard lock(m_mutex); + m_listeners.clear(); + } + + Iterator begin() { return m_listeners.begin(); } + Iterator end() { return m_listeners.end(); } + +private: + mutable std::mutex m_mutex; + std::vector m_listeners; + std::vector m_pendingUnsubscribes; + uint64_t m_nextId = 0; +}; + +using int8 = int8_t; +using int16 = int16_t; +using int32 = int32_t; +using int64 = int64_t; +using uint8 = uint8_t; +using uint16 = uint16_t; +using uint32 = uint32_t; +using uint64 = uint64_t; +using byte = uint8_t; + +class RefCounted { +public: + RefCounted() : m_refCount(1) {} + virtual ~RefCounted() = default; + + void AddRef() { ++m_refCount; } + void Release() { + if (--m_refCount == 0) { + delete this; + } + } + + uint32_t GetRefCount() const { return m_refCount.load(); } + +protected: + std::atomic m_refCount; +}; + +template +using Ref = std::shared_ptr; + +template +using UniqueRef = std::unique_ptr; + +} // namespace Core +} // namespace XCEngine + +namespace XCEngine { +namespace Debug { + +enum class LogLevel : uint8_t { + Verbose = 0, + Debug = 1, + Info = 2, + Warning = 3, + Error = 4, + Fatal = 5 +}; + +enum class LogCategory { + General, + Rendering, + Physics, + Audio, + Scripting, + Network, + Memory, + Threading, + FileSystem, + Custom +}; + +struct LogEntry { + LogLevel level; + LogCategory category; + String message; + String file; + int32 line; + String function; + uint64 timestamp; + uint32 threadId; +}; + +class ILogSink { +public: + virtual ~ILogSink() = default; + virtual void Log(const LogEntry& entry) = 0; + virtual void Flush() = 0; +}; + +class ConsoleLogSink : public ILogSink { +public: + void Log(const LogEntry& entry) override; + void Flush() override; + void SetColorOutput(bool enable); + void SetMinimumLevel(LogLevel level); +}; + +class FileLogSink : public ILogSink { +public: + explicit FileLogSink(const String& filePath); + ~FileLogSink(); + void Log(const LogEntry& entry) override; + void Flush() override; +private: + String m_filePath; + FileWriter m_writer; +}; + +class Logger { +public: + static Logger& Get(); + + void Initialize(); + void Shutdown(); + + void AddSink(std::unique_ptr sink); + void RemoveSink(ILogSink* sink); + + void Log(LogLevel level, LogCategory category, + const String& message, const char* file = nullptr, + int32 line = 0, const char* function = nullptr); + + void Verbose(LogCategory category, const String& message); + void Debug(LogCategory category, const String& message); + void Info(LogCategory category, const String& message); + void Warning(LogCategory category, const String& message); + void Error(LogCategory category, const String& message); + void Fatal(LogCategory category, const String& message); + + void SetMinimumLevel(LogLevel level); + void SetCategoryEnabled(LogCategory category, bool enabled); +}; + +#define XE_LOG(category, level, message) \ + XCEngine::Debug::Logger::Get().Log(level, category, message, __FILE__, __LINE__, __FUNCTION__) + +#define XE_ASSERT(condition, message) \ + if (!(condition)) { \ + XCEngine::Debug::Logger::Get().Fatal(XCEngine::Debug::LogCategory::General, message); \ + __debugbreak(); \ + } + +class Profiler { +public: + static Profiler& Get(); + + void Initialize(); + void Shutdown(); + + void BeginProfile(const char* name); + void EndProfile(); + + void BeginFrame(); + void EndFrame(); + + void MarkEvent(const char* name, uint64_t timestamp, uint32_t threadId); + void SetMarker(const char* name, uint32_t color); + + void ExportChromeTracing(const String& filePath); +}; + +#define XE_PROFILE_BEGIN(name) XCEngine::Debug::Profiler::Get().BeginProfile(name) +#define XE_PROFILE_END() XCEngine::Debug::Profiler::Get().EndProfile() +#define XE_PROFILE_FUNCTION() XE_PROFILE_BEGIN(__FUNCTION__) + +} // namespace Debug +} // namespace XCEngine +``` + +--- + +## 第二章 组件系统 + +### 2.1 组件基类 + +```cpp +namespace XCEngine { + +class Scene; +class GameObject; +class TransformComponent; + +// 组件类型注册(用于运行时类型识别) +class ComponentTypeRegistry { +public: + static ComponentTypeRegistry& Get(); + + template + static uint32_t GetTypeId() { + static uint32_t id = Get().Register(typeid(T).name(), static_cast(-1)); + return id; + } + + template + static uint32_t GetTypeId(const char* typeName) { + static uint32_t id = Get().Register(typeName, static_cast(-1)); + return id; + } + + static uint32_t GetTypeIdFromName(const char* typeName) { + return Get().GetIdByName(typeName); + } + + static const char* GetTypeName(uint32_t typeId) { + return Get().GetNameById(typeId); + } + +private: + uint32_t Register(const char* typeName, uint32_t suggestedId); + uint32_t GetIdByName(const char* typeName) const; + const char* GetNameById(uint32_t typeId) const; + + std::atomic m_nextTypeId{0}; + std::unordered_map m_idToName; + std::unordered_map m_nameToId; + Mutex m_mutex; +}; + +// 组件基类(类Unity MonoBehaviour) +class Component { +public: + Component(); + virtual ~Component(); + + GameObject* gameObject() const { return m_gameObject; } + TransformComponent& transform() const { return m_gameObject->GetTransform(); } + + bool IsEnabled() const { return m_enabled; } + void SetEnabled(bool enabled) { m_enabled = enabled; } + + Scene* GetScene() const; + + template + T* GetComponent() const { return m_gameObject->GetComponent(); } + + template + std::vector GetComponents() const { return m_gameObject->GetComponents(); } + + virtual void Awake() {} + virtual void Start() {} + virtual void Update(float deltaTime) {} + virtual void FixedUpdate() {} + virtual void LateUpdate(float deltaTime) {} + virtual void OnDestroy() {} + virtual void OnEnable() {} + virtual void OnDisable() {} + +protected: + GameObject* m_gameObject = nullptr; + bool m_enabled = true; + + friend class GameObject; +}; + +} // namespace XCEngine +``` + +### 2.2 Transform组件 + +```cpp +namespace XCEngine { + +class TransformComponent : public Component { +public: + Vector3 GetLocalPosition() const { return m_localPosition; } + void SetLocalPosition(const Vector3& position) { m_localPosition = position; SetDirty(); } + + Quaternion GetLocalRotation() const { return m_localRotation; } + void SetLocalRotation(const Quaternion& rotation) { m_localRotation = rotation; SetDirty(); } + + Vector3 GetLocalScale() const { return m_localScale; } + void SetLocalScale(const Vector3& scale) { m_localScale = scale; SetDirty(); } + + Vector3 GetPosition() const; + void SetPosition(const Vector3& position); + + Quaternion GetRotation() const; + void SetRotation(const Quaternion& rotation); + + Vector3 GetScale() const; + void SetScale(const Vector3& scale); + + Vector3 GetForward() const { return GetRotation() * Vector3::Forward(); } + Vector3 GetRight() const { return GetRotation() * Vector3::Right(); } + Vector3 GetUp() const { return GetRotation() * Vector3::Up(); } + + const Matrix4x4& GetLocalToWorldMatrix() const; + Matrix4x4 GetWorldToLocalMatrix() const; + + TransformComponent* GetParent() const { return m_parent; } + void SetParent(TransformComponent* parent, bool worldPositionStays = true); + + int GetChildCount() const { return static_cast(m_children.size()); } + TransformComponent* GetChild(int index) const; + TransformComponent* Find(const String& name) const; + + void DetachChildren(); + void SetAsFirstSibling(); + void SetAsLastSibling(); + void SetSiblingIndex(int index); + int GetSiblingIndex() const; + + void LookAt(const Vector3& target); + void LookAt(const Vector3& target, const Vector3& up); + void Rotate(const Vector3& eulers); + void Rotate(const Vector3& axis, float angle); + void Translate(const Vector3& translation); + void Translate(const Vector3& translation, Math::Space relativeTo); + + Vector3 TransformPoint(const Vector3& point) const; + Vector3 InverseTransformPoint(const Vector3& point) const; + Vector3 TransformDirection(const Vector3& direction) const; + Vector3 InverseTransformDirection(const Vector3& direction) const; + + void SetDirty() { m_dirty = true; } + +private: + Vector3 m_localPosition = Vector3::Zero(); + Quaternion m_localRotation = Quaternion::Identity(); + Vector3 m_localScale = Vector3::One(); + + TransformComponent* m_parent = nullptr; + std::vector m_children; + + mutable Matrix4x4 m_localToWorldMatrix; + mutable Matrix4x4 m_worldToLocalMatrix; + mutable Vector3 m_worldPosition; + mutable Quaternion m_worldRotation; + mutable Vector3 m_worldScale; + mutable bool m_dirty = true; + + void UpdateWorldTransform() const; + + friend class GameObject; +}; + +} // namespace XCEngine +``` + +### 2.3 GameObject + +```cpp +namespace XCEngine { + +class Scene; + +class GameObject { +public: + GameObject(); + ~GameObject(); + + struct ConstructParams { + String name = "GameObject"; + GameObject* parent = nullptr; + bool active = true; + }; + + static GameObject* Create(const ConstructParams& params = {}); + static void Destroy(GameObject* obj); + + String name; + bool active = true; + + TransformComponent& GetTransform() { return *m_transform; } + const TransformComponent& GetTransform() const { return *m_transform; } + + Scene* GetScene() const { return m_scene; } + + template + T* AddComponent(); + + template + void RemoveComponent(); + + template + T* GetComponent() const; + + template + std::vector GetComponents() const; + + template + T* GetComponentInChildren() const; + + template + std::vector GetComponentsInChildren() const; + + template + T* GetComponentInParent() const; + + GameObject* GetParent() const; + void SetParent(GameObject* parent); + void SetParent(GameObject* parent, bool worldPositionStays); + const std::vector& GetChildren() const; + GameObject* GetChild(int index) const; + int GetChildCount() const; + int GetSiblingIndex() const; + void SetSiblingIndex(int index); + + void SetActive(bool active); + bool IsActive() const; + bool IsActiveInHierarchy() const; + + static GameObject* Find(const String& name); + static std::vector FindObjectsOfType(); + static std::vector FindGameObjectsWithTag(const String& tag); + + void Destroy(); + +private: + void AddComponentInternal(Component* component); + void RemoveComponentInternal(Component* component); + + std::vector> m_components; + std::unordered_map m_componentTypeIndex; + + std::vector m_children; + GameObject* m_parent = nullptr; + Scene* m_scene = nullptr; + + std::unique_ptr m_transform; + + void Initialize(const ConstructParams& params); + + friend class Scene; + friend class TransformComponent; +}; + +inline GameObject::GameObject() { +} + +inline GameObject::~GameObject() { + for (auto* child : m_children) { + delete child; + } +} + +inline GameObject* GameObject::Create(const ConstructParams& params) { + GameObject* obj = new GameObject(); + obj->Initialize(params); + return obj; +} + +inline void GameObject::Destroy(GameObject* obj) { + delete obj; +} + +inline void GameObject::Initialize(const ConstructParams& params) { + name = params.name; + active = params.active; + + m_transform = std::make_unique(); + m_transform->m_gameObject = this; + + if (params.parent) { + params.parent->m_children.push_back(this); + m_parent = params.parent; + } +} + +inline void GameObject::Destroy() { + if (m_scene) { + m_scene->DestroyGameObject(this); + } else { + delete this; + } +} + +inline GameObject* GameObject::Find(const String& name) { + return SceneManager::Get().GetActiveScene()->Find(name); +} + +inline std::vector GameObject::FindObjectsOfType() { + return SceneManager::Get().GetActiveScene()->FindObjectsOfType(); +} + +inline std::vector GameObject::FindGameObjectsWithTag(const String& tag) { + return SceneManager::Get().GetActiveScene()->FindGameObjectsWithTag(tag); +} + +} // namespace XCEngine +``` + +--- + +## 第三章 场景系统 + +### 3.1 Scene + +```cpp +namespace XCEngine { + +class Scene { +public: + Scene(); + ~Scene(); + + const String& GetName() const { return m_name; } + void SetName(const String& name) { m_name = name; } + + GameObject* CreateGameObject(const String& name = "GameObject") { + GameObject::ConstructParams params; + params.name = name; + params.parent = nullptr; + params.active = true; + + GameObject* obj = GameObject::Create(params); + obj->m_scene = this; + AddGameObject(obj); + return obj; + } + + GameObject* CreateGameObject(const String& name, GameObject* parent) { + GameObject::ConstructParams params; + params.name = name; + params.parent = parent; + params.active = true; + + GameObject* obj = GameObject::Create(params); + obj->m_scene = this; + AddGameObject(obj); + return obj; + } + + void DestroyGameObject(GameObject* obj); + + std::vector GetRootGameObjects() const { + std::vector roots; + roots.reserve(m_gameObjects.size() / 2); + for (auto& obj : m_gameObjects) { + if (obj->GetParent() == nullptr) { + roots.push_back(obj.get()); + } + } + return roots; + } + + GameObject* Find(const String& name) const; + GameObject* FindGameObjectWithTag(const String& tag) const; + std::vector FindGameObjectsWithTag(const String& tag) const; + template + std::vector FindObjectsOfType() const; + template + T* FindObjectOfType() const; + + bool IsActive() const { return m_isActive; } + void SetActive(bool active); + + void Load(const String& filePath); + void LoadAsync(const String& filePath, std::function callback); + void Save(const String& filePath); + + void Update(float deltaTime); + void FixedUpdate(float fixedDeltaTime); + void LateUpdate(float deltaTime); + + void DebugDraw(); + int GetObjectCount() const { return m_gameObjects.size(); } + +private: + void AddGameObject(GameObject* obj); + void RemoveGameObject(GameObject* obj); + + String m_name; + std::vector> m_gameObjects; + bool m_isActive = true; + + friend class GameObject; + friend class SceneManager; +}; + +class SceneManager { +public: + static SceneManager& Get(); + + void Initialize(); + void Shutdown(); + + Scene* CreateScene(const String& name); + void LoadScene(const String& filePath); + void LoadSceneAsync(const String& filePath, std::function callback); + void UnloadScene(Scene* scene); + void UnloadScene(const String& sceneName); + + void SetActiveScene(Scene* scene); + void SetActiveScene(const String& sceneName); + Scene* GetActiveScene() const; + + Scene* GetScene(const String& name) const; + std::vector GetAllScenes() const; + + void Update(float deltaTime); + void FixedUpdate(float fixedDeltaTime); + void LateUpdate(float deltaTime); + + Event OnSceneLoaded; + Event OnSceneUnloaded; + Event OnActiveSceneChanged; + +private: + SceneManager() = default; + + std::vector> m_scenes; + Scene* m_activeScene = nullptr; + Scene* m_loadingScene = nullptr; + + std::unordered_map m_sceneNameMap; + std::function m_loadCallback; + bool m_loading = false; +}; + +// GameObject创建辅助类 +class GameObjectBuilder { +public: + explicit GameObjectBuilder(const String& name = "GameObject"); + ~GameObjectBuilder() = default; + + template + GameObjectBuilder& AddComponent(Args&&... args); + + GameObject* Build(); + +private: + String m_name; + std::vector> m_components; +}; + +} // namespace XCEngine +``` + +--- + +## 第四章 渲染系统 + +> **借鉴 Unity 渲染架构设计** + +### 4.0 公共类型定义 + +```cpp +namespace XCEngine { +namespace Rendering { + +// ============================================ +// 前置类型定义 - 资源基类 +// ============================================ + +enum class ResourceLoadState { + Undefined, + Unloaded, + Loading, + Loaded, + Unloading, + Failed +}; + +enum class ResourceType { + Mesh, + Texture, + Shader, + Material, + ComputeBuffer, + GraphicsBuffer, + Sampler, + RenderTarget, + DepthStencil, + VertexBuffer, + IndexBuffer, + Unknown +}; + +class IResource { +public: + virtual ~IResource() = default; + + virtual void SetName(const std::string& name) { m_name = name; } + virtual const std::string& GetName() const { return m_name; } + + virtual ResourceType GetType() const = 0; + virtual ResourceLoadState GetLoadState() const { return m_loadState; } + + virtual bool IsValid() const { return m_loadState == ResourceLoadState::Loaded; } + virtual void Load() = 0; + virtual void Unload() = 0; + + virtual int GetRefCount() const { return m_refCount.load(); } + virtual void AddRef() { m_refCount.fetch_add(1); } + virtual void Release() { + if (m_refCount.fetch_sub(1) == 1) { + delete this; + } + } + +protected: + IResource() : m_loadState(ResourceLoadState::Unloaded), m_memoryUsage(0) {} + + std::string m_name; + ResourceLoadState m_loadState; + uint64_t m_memoryUsage; + std::atomic m_refCount{1}; +}; + +// ============================================ +// 缓冲区类型定义 +// ============================================ + +class VertexBuffer : public IResource { +public: + ResourceType GetType() const override { return ResourceType::VertexBuffer; } + + void Load() override {} + void Unload() override {} + + uint32_t GetVertexCount() const { return m_vertexCount; } + uint32_t GetStride() const { return m_stride; } + uint64_t GetSize() const { return m_size; } + + void SetData(const void* data, uint64_t size); + void* Map(); + void Unmap(); + +private: + uint32_t m_vertexCount = 0; + uint32_t m_stride = 0; + uint64_t m_size = 0; + void* m_nativeHandle = nullptr; +}; + +class IndexBuffer : public IResource { +public: + ResourceType GetType() const override { return ResourceType::IndexBuffer; } + + void Load() override {} + void Unload() override {} + + uint32_t GetIndexCount() const { return m_indexCount; } + bool Is32Bit() const { return m_is32Bit; } + uint64_t GetSize() const { return m_size; } + + void SetData(const void* data, uint64_t size); + void* Map(); + void Unmap(); + +private: + uint32_t m_indexCount = 0; + bool m_is32Bit = false; + uint64_t m_size = 0; + void* m_nativeHandle = nullptr; +}; + +// ============================================ +// 渲染目标类型定义 +// ============================================ + +struct RenderTargetDesc { + uint32_t width = 0; + uint32_t height = 0; + Format format = Format::R8G8B8A8_UNorm; + SampleCount sampleCount = SampleCount::Count1; + uint32_t mipLevels = 1; + uint32_t arraySize = 1; + bool enableUAV = false; + String name; +}; + +class RenderTarget : public IResource { +public: + ResourceType GetType() const override { return ResourceType::RenderTarget; } + + void Load() override {} + void Unload() override {} + + uint32_t GetWidth() const { return m_width; } + uint32_t GetHeight() const { return m_height; } + Format GetFormat() const { return m_format; } + + void* GetNativeHandle() const { return m_nativeHandle; } + + IShaderResourceView* GetSRV() { return m_srv.get(); } + IRenderTargetView* GetRTV() { return m_rtv.get(); } + +private: + uint32_t m_width = 0; + uint32_t m_height = 0; + Format m_format; + void* m_nativeHandle = nullptr; + std::unique_ptr m_srv; + std::unique_ptr m_rtv; +}; + +struct DepthStencilDesc { + uint32_t width = 0; + uint32_t height = 0; + Format format = Format::D24_UNorm_S8_UInt; + SampleCount sampleCount = SampleCount::Count1; + bool bindAsShaderResource = false; + String name; +}; + +class DepthStencil : public IResource { +public: + ResourceType GetType() const override { return ResourceType::DepthStencil; } + + void Load() override {} + void Unload() override {} + + uint32_t GetWidth() const { return m_width; } + uint32_t GetHeight() const { return m_height; } + Format GetFormat() const { return m_format; } + + void* GetNativeHandle() const { return m_nativeHandle; } + + IDepthStencilView* GetDSV() { return m_dsv.get(); } + IShaderResourceView* GetSRV() { return m_srv.get(); } + +private: + uint32_t m_width = 0; + uint32_t m_height = 0; + Format m_format; + void* m_nativeHandle = nullptr; + std::unique_ptr m_dsv; + std::unique_ptr m_srv; +}; + +// ============================================ +// 渲染通道描述 +// ============================================ + +struct RenderPassAttachmentDesc { + RenderTarget* renderTarget = nullptr; + DepthStencil* depthStencil = nullptr; + LoadAction loadAction = LoadAction::Clear; + StoreAction storeAction = StoreAction::Store; + Color clearColor = Color::Black(); + float clearDepth = 1.0f; + uint8_t clearStencil = 0; +}; + +struct RenderPassDesc { + RenderPassAttachmentDesc* colorAttachments = nullptr; + uint32_t colorAttachmentCount = 0; + RenderPassAttachmentDesc* depthStencilAttachment = nullptr; + Rect viewport; + Rect scissor; +}; + +// ============================================ +// 基础枚举类型 +// ============================================ + +enum class Format { + Unknown = 0, + R8_UNorm = 61, + R8G8_UNorm = 49, + R8G8B8A8_UNorm = 28, + R16G16B16A16_Float = 10, + R32G32B32A32_Float = 2, + R16_Float = 54, + R32_Float = 41, + D16_UNorm = 55, + D24_UNorm_S8_UInt = 45, + D32_Float = 40, + BC1_UNorm = 71, + BC2_UNorm = 74, + BC3_UNorm = 77, + BC4_UNorm = 80, + BC5_UNorm = 83, + BC6H_UF16 = 95, + BC7_UNorm = 98 +}; + +enum class SampleCount : uint32_t { + Count1 = 1, + Count2 = 2, + Count4 = 4, + Count8 = 8 +}; + +enum class CubemapFace : uint8_t { + PositiveX = 0, + NegativeX = 1, + PositiveY = 2, + NegativeY = 3, + PositiveZ = 4, + NegativeZ = 5 +}; + +struct Frustum { + Plane planes[6]; + + bool Contains(const Vector3& point) const; + bool Contains(const Sphere& sphere) const; + bool Contains(const Bounds& bounds) const; + bool Intersects(const Bounds& bounds) const; +}; + +enum class FilterMode { + Point = 0, + Bilinear = 1, + Trilinear = 2 +}; + +enum class TextureWrapMode { + Repeat = 0, + Clamp = 1, + Mirror = 2, + MirrorOnce = 3 +}; + +enum class MeshTopology { + Points, + Lines, + LineStrip, + Triangles, + TriangleStrip, + Quads +}; + +struct Bounds { + Vector3 center; + Vector3 extents; + Vector3 min; + Vector3 max; + + Bounds() : center(Vector3::Zero()), extents(Vector3::Zero()) {} + Bounds(const Vector3& center, const Vector3& size) + : center(center), extents(size * 0.5f) { + min = center - extents; + max = center + extents; + } + + void SetMinMax(const Vector3& min, const Vector3& max) { + this->min = min; + this->max = max; + center = (min + max) * 0.5f; + extents = (max - min) * 0.5f; + } + + bool Intersects(const Bounds& other) const; + bool Contains(const Vector3& point) const; + + void Encapsulate(const Vector3& point); + void Encapsulate(const Bounds& bounds); + + void Expand(float amount); + void Expand(const Vector3& amount); + + Vector3 GetClosestPoint(const Vector3& point) const; +}; + +struct QualityLevel { + enum { + Fastest = 0, + Fast = 1, + Simple = 2, + Good = 3, + High = 4, + Ultra = 5 + }; +}; + +class StringView { +public: + StringView() : m_data(nullptr), m_length(0) {} + StringView(const char* str); + StringView(const char* str, size_t len); + StringView(const String& str); + + const char* Data() const { return m_data; } + size_t Length() const { return m_length; } + + bool Empty() const { return m_length == 0; } + + char operator[](size_t index) const { return m_data[index]; } + + int Compare(const StringView& other) const; + bool operator==(const StringView& other) const; + bool operator!=(const StringView& other) const; + +private: + const char* m_data; + size_t m_length; +}; + +class Texture { +public: + virtual ~Texture() = default; + + uint32_t GetWidth() const { return m_width; } + uint32_t GetHeight() const { return m_height; } + uint32_t GetDepth() const { return m_depth; } + uint32_t GetMipLevels() const { return m_mipLevels; } + Format GetFormat() const { return m_format; } + + FilterMode GetFilterMode() const { return m_filterMode; } + void SetFilterMode(FilterMode mode) { m_filterMode = mode; } + + TextureWrapMode GetWrapMode() const { return m_wrapMode; } + void SetWrapMode(TextureWrapMode mode) { m_wrapMode = mode; } + + void* GetNativeHandle() const { return m_nativeHandle; } + +protected: + uint32_t m_width = 0; + uint32_t m_height = 0; + uint32_t m_depth = 1; + uint32_t m_mipLevels = 1; + Format m_format = Format::R8G8B8A8_UNorm; + FilterMode m_filterMode = FilterMode::Bilinear; + TextureWrapMode m_wrapMode = TextureWrapMode::Clamp; + void* m_nativeHandle = nullptr; +}; + +class RenderTargetIdentifier { +public: + RenderTargetIdentifier(); + RenderTargetIdentifier(int nameID); + RenderTargetIdentifier(const String& name); + RenderTargetIdentifier(Texture* texture); + + bool IsValid() const { return m_type != Buffer || m_nameID != -1; } + bool operator==(const RenderTargetIdentifier& other) const; + bool operator!=(const RenderTargetIdentifier& other) const { return !(*this == other); } + + int GetType() const { return m_type; } + int GetNameID() const { return m_nameID; } + Texture* GetTexture() const { return m_texture; } + +private: + int m_type = Buffer; + int m_nameID = -1; + Texture* m_texture = nullptr; + + enum { Buffer, Texture2D, RenderTarget }; +}; + +class CommandBuffer { +public: + CommandBuffer(); + ~CommandBuffer(); + + void Clear(); + void BeginSample(const char* name); + void EndSample(const char* name); + void BeginDebugGroup(const char* name); + void EndDebugGroup(); + + void SetRenderTarget( + RenderTargetIdentifier colorTarget, + RenderTargetIdentifier depthTarget, + int mipLevel = 0, + CubemapFace cubemapFace = CubemapFace::PositiveX, + bool depthIsWritable = true + ); + + void SetRenderTarget( + const std::vector& colorTargets, + RenderTargetIdentifier depthTarget, + int mipLevel = 0, + CubemapFace cubemapFace = CubemapFace::PositiveX, + bool depthIsWritable = true + ); + + void SetViewport(const Rect& rect); + void SetScissor(const Rect& rect); + + void SetViewMatrix(const Matrix4x4& matrix); + void SetProjectionMatrix(const Matrix4x4& matrix); + + void DrawMeshInstanced( + const Mesh& mesh, + int submeshIndex, + Material* material, + int shaderPass, + const std::vector& matrices + ); + + void DrawMeshInstancedIndirect( + const Mesh& mesh, + int submeshIndex, + Material* material, + int shaderPass, + const ComputeBuffer& argsBuffer, + int argsOffset + ); + + void DrawProcedural( + Material* material, + int shaderPass, + MeshTopology topology, + int vertexCount, + int instanceCount + ); + + void Blit( + Material* material, + int pass, + RenderTargetIdentifier source, + RenderTargetIdentifier dest + ); + + void CopyTexture( + RenderTargetIdentifier source, + RenderTargetIdentifier dest + ); + + void GetTemporaryRT( + const String& name, + int width, + int height, + Format format = Format::R8G8B8A8_UNorm, + FilterMode filter = FilterMode::Bilinear, + TextureWrapMode wrap = TextureWrapMode::Clamp, + int depthBufferBits = 0 + ); + + void ReleaseTemporaryRT(const String& name); + + void GetCommandBufferPtr(void** ptr); + +private: + std::vector m_data; + std::vector m_sampleNames; + int m_sampleDepth = 0; +}; + +class Mesh : public IResource { +public: + Mesh(); + ~Mesh(); + + void SetVertices(const std::vector& vertices); + void SetNormals(const std::vector& normals); + void SetTangents(const std::vector& tangents); + void SetUVs(int channel, const std::vector& uvs); + void SetUVs(int channel, const std::vector& uvs); + void SetTriangles(const std::vector& triangles, int submesh); + void SetIndices(const std::vector& indices, int submesh); + void SetIndices(const std::vector& indices, int submesh); + + const std::vector& GetVertices() const { return m_vertices; } + const std::vector& GetNormals() const { return m_normals; } + const std::vector& GetTangents() const { return m_tangents; } + + int GetSubmeshCount() const { return m_submeshes.size(); } + const struct SubmeshDescriptor& GetSubmesh(int index) const; + + int GetVertexCount() const { return static_cast(m_vertices.size()); } + int GetIndexCount(int submesh) const; + + MeshTopology GetTopology(int submesh) const; + void SetTopology(MeshTopology topology, int submesh); + + void RecalculateNormals(); + void RecalculateTangents(); + void RecalculateBounds(); + + void Optimize(); + + bool IsUse32BitIndexBuffer() const { return m_use32BitIndex; } + + struct MeshData { + std::vector vertices; + std::vector normals; + std::vector tangents; + std::vector uvs[8]; + std::vector indices32; + std::vector indices16; + }; + void GetMeshData(MeshData& data) const; + +private: + std::vector m_vertices; + std::vector m_normals; + std::vector m_tangents; + std::vector m_uvs[8]; + + struct SubmeshDescriptor { + int indexStart; + int indexCount; + int baseVertex; + MeshTopology topology; + }; + std::vector m_submeshes; + + Bounds m_bounds; + bool m_use32BitIndex = false; + bool m_hasVertices = false; + bool m_hasNormals = false; + bool m_hasTangents = false; + + friend class MeshCollider; + friend class SkinnedMeshRenderer; +}; + +class ComputeBuffer : public IResource { +public: + enum class Type { + Default, + Raw, + Append, + Counter, + Structured, + ByteAddress + }; + + ComputeBuffer(Type type, int count, int stride); + ~ComputeBuffer(); + + int GetCount() const { return m_count; } + int GetStride() const { return m_stride; } + Type GetType() const { return m_type; } + + void SetData(const void* data); + void GetData(void* data) const; + + void SetCounterValue(uint32_t value); + uint32_t GetCounterValue() const; + +private: + Type m_type; + int m_count; + int m_stride; + void* m_buffer; +}; + +class GraphicsBuffer : public IResource { +public: + enum class Target { + Constant, + IndexBuffer, + VertexBuffer, + Structured, + Append, + Counter, + ReadWrite + }; + + GraphicsBuffer(Target target, uint32_t count, uint32_t stride); + virtual ~GraphicsBuffer(); + + Target GetTarget() const { return m_target; } + uint32_t GetCount() const { return m_count; } + uint32_t GetStride() const { return m_stride; } + uint64_t GetSize() const { return m_size; } + + void SetData(const void* data); + void GetData(void* data) const; + + void* Map(); + void Unmap(); + + void SetCounterValue(uint32_t value); + uint32_t GetCounterValue() const; + +private: + Target m_target; + uint32_t m_count = 0; + uint32_t m_stride = 0; + uint64_t m_size = 0; + void* m_buffer; +}; + +struct ShaderProgramDesc { + enum class Stage { + Vertex, + Fragment, + Compute, + Geometry, + Hull, + Domain + }; + + Stage stage; + String source; + String entryPoint; + + bool debug = false; + bool optimize = true; +}; + +} // namespace Rendering +} // namespace XCEngine +``` + +### 4.1 RHI 抽象层接口 + +```cpp +namespace XCEngine { +namespace RHI { + +// ============================================ +// 跨平台枚举类型 - 不暴露平台特定类型 +// ============================================ + +enum class GraphicsAPI { + Unknown, + Direct3D11, + Direct3D12, + Vulkan, + Metal, + OpenGL +}; + +enum class CommandListType { + Direct, + Compute, + Copy, + Bundle +}; + +enum class ShaderVisibility { + All = 0, + Vertex = 1, + Hull = 2, + Domain = 3, + Geometry = 4, + Pixel = 5, + Amplification = 6, + Mesh = 7 +}; + +enum class ResourceStateFlag : uint32_t { + Common = 0, + VertexBuffer = 1 << 0, + ConstantBuffer = 1 << 1, + IndexBuffer = 1 << 2, + RenderTarget = 1 << 3, + UnorderedAccess = 1 << 4, + DepthWrite = 1 << 5, + DepthRead = 1 << 6, + ShaderResource = 1 << 7, + IndirectArgument = 1 << 8, + CopyDest = 1 << 9, + CopySource = 1 << 10, + ResolveDest = 1 << 11, + ResolveSource = 1 << 12, + Present = 1 << 13, + RaytracingAccelerationStructure = 1 << 14, + ShadingRateSource = 1 << 15 +}; + +inline ResourceStateFlag operator|(ResourceStateFlag a, ResourceStateFlag b) { + return static_cast(static_cast(a) | static_cast(b)); +} + +inline ResourceStateFlag operator&(ResourceStateFlag a, ResourceStateFlag b) { + return static_cast(static_cast(a) & static_cast(b)); +} + +enum class DescriptorHeapType { + CBV_SRV_UAV, + Sampler, + RTV, + DSV +}; + +enum class QueryType { + Occlusion, + Timestamp, + PipelineStatistics +}; + +// ============================================ +// 描述结构体 +// ============================================ + +struct CommandQueueDesc { + CommandListType type = CommandListType::Direct; + int priority = 0; + const char* name = nullptr; +}; + +struct DescriptorHeapDesc { + DescriptorHeapType type; + uint32_t count; + bool shaderVisible; + const char* name; +}; + +struct QueryHeapDesc { + QueryType type; + uint32_t count; + const char* name; +}; + +struct SwapChainDesc { + uint32_t width; + uint32_t height; + Format format; + uint32_t bufferCount; + bool vsync; + bool fullscreen; +}; + +class ICommandQueue { +public: + virtual ~ICommandQueue() = default; + + virtual void ExecuteCommandLists(ICommandList** lists, uint32_t count) = 0; + virtual void Signal(IFence* fence, uint64_t value) = 0; + virtual void Wait(IFence* fence, uint64_t value) = 0; + + virtual uint64_t GetTimestampFrequency() const = 0; +}; + +class ICommandAllocator { +public: + virtual ~ICommandAllocator() = default; + virtual void Reset() = 0; +}; + +class IFence { +public: + virtual ~IFence() = default; + + virtual uint64_t GetCompletedValue() const = 0; + virtual void Signal(uint64_t value) = 0; + virtual void Wait(uint64_t value) = 0; + virtual void Wait(uint64_t value, uint64_t timeoutMs) = 0; +}; + +class IDescriptorHeap { +public: + virtual ~IDescriptorHeap() = default; + + virtual DescriptorHeapType GetType() const = 0; + virtual uint32_t GetDescriptorCount() const = 0; + + virtual void* GetCPUDescriptorHandle(uint32_t index) const = 0; + virtual uint64_t GetGPUDescriptorHandle(uint32_t index) const = 0; + + virtual void SetName(const String& name) = 0; +}; + +class IQueryHeap { +public: + virtual ~IQueryHeap() = default; + + virtual QueryType GetType() const = 0; + virtual uint32_t GetCount() const = 0; + + virtual void Begin(ICommandList* cmdList, uint32_t index) = 0; + virtual void End(ICommandList* cmdList, uint32_t index) = 0; + virtual void GetData(uint32_t index, void* data, uint32_t dataSize) = 0; +}; + +class ISwapChain { +public: + virtual ~ISwapChain() = default; + + virtual bool Initialize(const SwapChainDesc& desc, void* windowHandle) = 0; + virtual void Shutdown() = 0; + + virtual bool Present() = 0; + virtual bool Resize(uint32_t width, uint32_t height) = 0; + + virtual uint32_t GetCurrentBufferIndex() const = 0; + virtual RenderTexture* GetBuffer(uint32_t index) = 0; + + virtual void SetFullscreen(bool fullscreen) = 0; + virtual bool IsFullscreen() const = 0; +}; + +struct RootParameter { + enum class Type { DescriptorTable, Constants, CBV, SRV, UAV, Sampler }; + Type type; + uint32_t shaderRegister; + uint32_t registerSpace; + ShaderVisibility visibility = ShaderVisibility::All; +}; + +struct RootSignatureDesc { + RootParameter* parameters; + uint32_t parameterCount; + uint32_t flags; +}; + +class RootSignature { +public: + virtual ~RootSignature() = default; + virtual bool Initialize(const RootSignatureDesc& desc) = 0; + virtual void SetName(const String& name) = 0; +}; + +struct PipelineDesc { + RootSignature* rootSignature; + Shader* vertexShader; + Shader* pixelShader; + Shader* computeShader; + RenderState renderState; + uint32_t numRenderTargets; + Format rtvFormats[8]; + Format dsvFormat; +}; + +class PipelineStateObject { +public: + virtual ~PipelineStateObject() = default; + virtual void SetName(const String& name) = 0; +}; + +class ICommandList { +public: + virtual ~ICommandList() = default; + + virtual void Reset(ICommandAllocator* allocator) = 0; + virtual void Close() = 0; + + virtual void BeginRenderPass(const RenderPassDesc& desc) = 0; + virtual void EndRenderPass() = 0; + + virtual void SetPipelineState(PipelineStateObject* pso) = 0; + virtual void SetRootSignature(RootSignature* signature) = 0; + + virtual void SetVertexBuffer(uint32_t slot, VertexBuffer* buffer, uint32_t offset = 0) = 0; + virtual void SetIndexBuffer(IndexBuffer* buffer, uint32_t offset = 0) = 0; + + virtual void SetDescriptorHeap(IDescriptorHeap* heap) = 0; + virtual void SetGraphicsDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) = 0; + virtual void SetComputeDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) = 0; + + virtual void DrawInstanced(uint32_t vertexCountPerInstance, uint32_t instanceCount, + uint32_t startVertex, uint32_t startInstance) = 0; + virtual void DrawIndexedInstanced(uint32_t indexCountPerInstance, uint32_t instanceCount, + uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) = 0; + virtual void Dispatch(uint32_t x, uint32_t y, uint32_t z) = 0; + + virtual void SetViewports(const Viewport* viewports, uint32_t count) = 0; + virtual void SetScissorRects(const Rect* rects, uint32_t count) = 0; + virtual void SetRenderTargets(const RenderTarget* const* targets, uint32_t count, + const DepthStencil* depthStencil) = 0; + + virtual void ClearRenderTargetView(const RenderTarget* target, const float color[4]) = 0; + virtual void ClearDepthStencilView(const DepthStencil* depth, float depthValue, uint8_t stencil) = 0; + + virtual void CopyResource(IResource* dst, const IResource* src) = 0; + virtual void CopyBuffer(IResource* dst, uint64_t dstOffset, const IResource* src, + uint64_t srcOffset, uint64_t size) = 0; + + virtual void ResourceBarrier(IResource* resource, ResourceStateFlag before, + ResourceStateFlag after) = 0; +}; + +class IShaderResourceView { +public: + virtual ~IShaderResourceView() = default; +}; + +class IRenderTargetView { +public: + virtual ~IRenderTargetView() = default; +}; + +class IDepthStencilView { +public: + virtual ~IDepthStencilView() = default; +}; + +class IRHIDevice { +public: + virtual ~IRHIDevice() = default; + + virtual GraphicsAPI GetAPI() const = 0; + virtual const char* GetAPIName() const = 0; + + virtual bool Initialize() = 0; + virtual void Shutdown() = 0; + + virtual bool CreateCommandQueue(ICommandQueue** queue, const CommandQueueDesc& desc) = 0; + virtual bool CreateCommandAllocator(ICommandAllocator** allocator) = 0; + virtual bool CreateCommandList(ICommandList** list, ICommandAllocator* allocator) = 0; + virtual bool CreateFence(IFence** fence) = 0; + + virtual bool CreateDescriptorHeap(IDescriptorHeap** heap, const DescriptorHeapDesc& desc) = 0; + virtual bool CreateQueryHeap(IQueryHeap** heap, const QueryHeapDesc& desc) = 0; + + virtual bool CreateRootSignature(RootSignature** signature, const RootSignatureDesc& desc) = 0; + virtual bool CreatePipelineState(PipelineStateObject** pso, const PipelineDesc& desc) = 0; + + virtual bool CreateSwapChain(ISwapChain** swapChain, const SwapChainDesc& desc, void* windowHandle) = 0; + virtual bool CreateRenderTarget(RenderTarget** target, const RenderTargetDesc& desc) = 0; + virtual bool CreateDepthStencil(DepthStencil** depthStencil, const DepthStencilDesc& desc) = 0; + + virtual void* GetNativeDevice() const = 0; +}; + +} // namespace RHI +} // namespace XCEngine +``` + + + +### 4.3 Direct3D 12 特有的 RHI 实现 + +```cpp +// ============================================ +// D3D12 前向声明 +// ============================================ +struct ID3D12Device; +struct ID3D12CommandQueue; +struct ID3D12CommandAllocator; +struct ID3D12GraphicsCommandList; +struct ID3D12DescriptorHeap; +struct ID3D12RootSignature; +struct ID3D12PipelineState; +struct ID3D12Fence; +struct ID3D12QueryHeap; +struct IDXGISwapChain3; + +template +class ComPtr; + +namespace XCEngine { +namespace RHI { +namespace D3D12 { + +enum class D3D12_COMMAND_LIST_TYPE { + DIRECT = 0, + BUNDLE = 1, + COMPUTE = 2, + COPY = 3 +}; + +enum class D3D12_DESCRIPTOR_HEAP_TYPE { + CBV_SRV_UAV = 0, + SAMPLER = 1, + RTV = 2, + DSV = 3, + NUM_TYPES = 4 +}; + +enum class D3D12_DESCRIPTOR_HEAP_FLAGS { + NONE = 0, + SHADER_VISIBLE = 1 +}; + +enum class D3D12_RESOURCE_STATES { + COMMON = 0, + VERTEX_AND_CONSTANT_BUFFER = 0x1, + INDEX_BUFFER = 0x2, + RENDER_TARGET = 0x4, + UNORDERED_ACCESS = 0x8, + DEPTH_WRITE = 0x10, + DEPTH_READ = 0x20, + NON_PIXEL_SHADER_RESOURCE = 0x40, + PIXEL_SHADER_RESOURCE = 0x80, + STREAM_OUT = 0x100, + INDIRECT_ARGUMENT = 0x200, + COPY_DEST = 0x400, + COPY_SOURCE = 0x800, + RESOLVE_DEST = 0x1000, + RESOLVE_SOURCE = 0x2000, + RAYTRACING_ACCELERATION_STRUCTURE = 0x4000, + SHADING_RATE_COARSE = 0x8000, + SHADING_RATE_FINE = 0x10000, + PRESENT = 0x0 +}; + +enum class D3D12_SRV_DIMENSION { + UNKNOWN = 0, + BUFFER = 1, + TEXTURE1D = 2, + TEXTURE1DARRAY = 3, + TEXTURE2D = 4, + TEXTURE2DARRAY = 5, + TEXTURE2DMS = 6, + TEXTURE2DMSARRAY = 7, + TEXTURE3D = 8, + TEXTURECUBE = 9, + TEXTURECUBEARRAY = 10 +}; + +enum class D3D12_UAV_DIMENSION { + UNKNOWN = 0, + BUFFER = 1, + TEXTURE1D = 2, + TEXTURE1DARRAY = 3, + TEXTURE2D = 4, + TEXTURE2DARRAY = 5, + TEXTURE3D = 8 +}; + +enum class D3D12_RTV_DIMENSION { + UNKNOWN = 0, + BUFFER = 1, + TEXTURE1D = 2, + TEXTURE1DARRAY = 3, + TEXTURE2D = 4, + TEXTURE2DARRAY = 5, + TEXTURE2DMS = 6, + TEXTURE2DMSARRAY = 7, + TEXTURE3D = 8 +}; + +enum class D3D12_DSV_DIMENSION { + UNKNOWN = 0, + TEXTURE1D = 1, + TEXTURE1DARRAY = 2, + TEXTURE2D = 3, + TEXTURE2DARRAY = 4, + TEXTURE2DMS = 5, + TEXTURE2DMSARRAY = 6 +}; + +enum class D3D12_ROOT_SIGNATURE_FLAGS { + NONE = 0, + ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT = 0x1, + DENY_VERTEX_SHADER_ROOT_ACCESS = 0x2, + DENY_HULL_SHADER_ROOT_ACCESS = 0x4, + DENY_DOMAIN_SHADER_ROOT_ACCESS = 0x8, + DENY_GEOMETRY_SHADER_ROOT_ACCESS = 0x10, + DENY_PIXEL_SHADER_ROOT_ACCESS = 0x20, + ALLOW_STREAM_PIPELINE = 0x40, + LOCAL_ROOT_SIGNATURE = 0x80 +}; + +enum class D3D12_ROOT_PARAMETER_TYPE { + DESCRIPTOR_TABLE = 0, + _32BIT_CONSTANTS = 1, + CBV = 2, + SRV = 3, + UAV = 4, + SAMPLER = 5 +}; + +enum class D3D12_SHADER_VISIBILITY { + ALL = 0, + VERTEX = 1, + HULL = 2, + DOMAIN = 3, + GEOMETRY = 4, + PIXEL = 5 +}; + +enum class D3D12_FILTER { + MIN_MAG_MIP_POINT = 0, + MIN_MAG_POINT_MIP_LINEAR = 0x1, + MIN_POINT_MAG_LINEAR_MIP_POINT = 0x2, + MIN_POINT_MAG_MIP_LINEAR = 0x3, + MIN_LINEAR_MAG_MIP_POINT = 0x4, + MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x5, + MIN_MAG_LINEAR_MIP_POINT = 0x6, + MIN_MAG_MIP_LINEAR = 0x7, + ANISOTROPIC = 0x15, + COMPARISON_MIN_MAG_MIP_POINT = 0x80, + COMPARISON_MIN_MAG_POINT_MIP_LINEAR = 0x81, + COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x82, + COMPARISON_MIN_POINT_MAG_MIP_LINEAR = 0x83, + COMPARISON_MIN_LINEAR_MAG_MIP_POINT = 0x84, + COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x85, + COMPARISON_MIN_MAG_LINEAR_MIP_POINT = 0x86, + COMPARISON_MIN_MAG_MIP_LINEAR = 0x87, + COMPARISON_ANISOTROPIC = 0x95 +}; + +enum class D3D12_TEXTURE_ADDRESS_MODE { + WRAP = 1, + MIRROR = 2, + CLAMP = 3, + BORDER = 4, + MIRROR_ONCE = 5 +}; + +enum class D3D12_COMPARISON_FUNC { + NEVER = 1, + LESS = 2, + EQUAL = 3, + LESS_EQUAL = 4, + GREATER = 5, + NOT_EQUAL = 6, + GREATER_EQUAL = 7, + ALWAYS = 8 +}; + +enum class D3D12_BLEND { + ZERO = 1, + ONE = 2, + SRC_COLOR = 3, + INV_SRC_COLOR = 4, + SRC_ALPHA = 5, + INV_SRC_ALPHA = 6, + DST_ALPHA = 7, + INV_DST_ALPHA = 8, + DST_COLOR = 9, + INV_DST_COLOR = 10, + SRC_ALPHA_SAT = 11, + BLEND_FACTOR = 14, + INV_BLEND_FACTOR = 15, + SRC1_COLOR = 16, + INV_SRC1_COLOR = 17, + SRC1_ALPHA = 18, + INV_SRC1_ALPHA = 19 +}; + +enum class D3D12_BLEND_OP { + ADD = 1, + SUBTRACT = 2, + REV_SUBTRACT = 3, + MIN = 4, + MAX = 5 +}; + +enum class D3D12_COLOR_WRITE_ENABLE { + RED = 1, + GREEN = 2, + BLUE = 4, + ALPHA = 8, + ALL = 15 +}; + +enum class D3D12_CULL_MODE { + NONE = 1, + FRONT = 2, + BACK = 3 +}; + +enum class D3D12_FILL_MODE { + WIREFRAME = 2, + SOLID = 3 +}; + +enum class D3D12_PRIMITIVE_TOPOLOGY_TYPE { + UNDEFINED = 0, + POINT = 1, + LINE = 2, + TRIANGLE = 3, + PATCH = 4 +}; + +enum class D3D12_PRIMITIVE_TOPOLOGY { + UNDEFINED = 0, + POINTLIST = 1, + LINELIST = 2, + LINESTRIP = 3, + TRIANGLELIST = 4, + TRIANGLESTRIP = 5, + TRIANGLEFAN = 6, + LINELIST_ADJ = 10, + LINESTRIP_ADJ = 11, + TRIANGLELIST_ADJ = 12, + TRIANGLESTRIP_ADJ = 13, + PATCHLIST_1 = 33, + PATCHLIST_2 = 34, + PATCHLIST_3 = 35, + PATCHLIST_4 = 36, + PATCHLIST_5 = 37, + PATCHLIST_6 = 38, + PATCHLIST_7 = 39, + PATCHLIST_8 = 40, + PATCHLIST_9 = 41, + PATCHLIST_10 = 42, + PATCHLIST_11 = 43, + PATCHLIST_12 = 44, + PATCHLIST_13 = 45, + PATCHLIST_14 = 46, + PATCHLIST_15 = 47, + PATCHLIST_16 = 48, + PATCHLIST_17 = 49, + PATCHLIST_18 = 50, + PATCHLIST_19 = 51, + PATCHLIST_20 = 52, + PATCHLIST_21 = 53, + PATCHLIST_22 = 54, + PATCHLIST_23 = 55, + PATCHLIST_24 = 56, + PATCHLIST_25 = 57, + PATCHLIST_26 = 58, + PATCHLIST_27 = 59, + PATCHLIST_28 = 60, + PATCHLIST_29 = 61, + PATCHLIST_30 = 62, + PATCHLIST_31 = 63, + PATCHLIST_32 = 64 +}; + +enum class D3D12_QUERY_TYPE { + OCCLUSION = 0, + TIMESTAMP = 1, + PIPELINE_STATISTICS = 2, + DEPTH_STENCIL_CLIP_CUT = 3 +}; + +enum class D3D12_QUERY_HEAP_TYPE { + OCCLUSION = 0, + TIMESTAMP = 1, + PIPELINE_STATISTICS = 2, + SO_STATISTICS = 3, + VIDEO_DECODE_STATISTICS = 4, + COPY_QUEUE_TIMESTAMP = 5, + TIME_STAMP = 6 +}; + +struct D3D12_CPU_DESCRIPTOR_HANDLE { + void* ptr; +}; + +struct D3D12_GPU_DESCRIPTOR_HANDLE { + uint64_t ptr; +}; + +struct D3D12_RESOURCE_BARRIER { + enum class Type { + TRANSITION, + ALIASING, + UDV + }; + + Type Type; + + union { + struct { + IResource* pResource; + int32_t Subresource; + D3D12_RESOURCE_STATES StateBefore; + D3D12_RESOURCE_STATES StateAfter; + } Transition; + + struct { + IResource* pResourceBefore; + IResource* pResourceAfter; + } Aliasing; + + struct { + IResource* pResource; + uint32_t NumRoadmapEntries; + uint32_t* pRoadmap; + D3D12_RESOURCE_STATES StateBefore; + D3D12_RESOURCE_STATES StateAfter; + } UAV; + }; +}; + +struct D3D12_VIEWPORT { + float TopLeftX; + float TopLeftY; + float Width; + float Height; + float MinDepth; + float MaxDepth; +}; + +struct D3D12_RECT { + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; +}; + +struct D3D12_INPUT_ELEMENT_DESC { + const char* SemanticName; + uint32_t SemanticIndex; + Format Format; + uint32_t InputSlot; + uint32_t AlignedByteOffset; + D3D12_INPUT_CLASSIFICATION InputSlotClass; + uint32_t InstanceDataStepRate; +}; + +enum class D3D12_INPUT_CLASSIFICATION { + PER_VERTEX_DATA = 0, + PER_INSTANCE_DATA = 1 +}; + +struct D3D12_SO_DECLARATION_ENTRY { + const char* SemanticName; + uint32_t SemanticIndex; + uint8_t StartComponent; + uint8_t ComponentCount; + uint8_t OutputSlot; +}; + +struct D3D12_SHADER_RESOURCE_VIEW_DESC { + D3D12_SRV_DIMENSION ViewDimension; + Format Format; + uint32_t Shader4ComponentMapping; + + union { + struct { + uint32_t MostDetailedMip; + uint32_t MipLevels; + uint32_t PlaneSlice; + float ResourceMinLODClamp; + } Texture2D; + + struct { + uint32_t MostDetailedMip; + uint32_t MipLevels; + uint32_t FirstArraySlice; + uint32_t ArraySize; + uint32_t PlaneSlice; + float ResourceMinLODClamp; + } Texture2DArray; + + struct { + uint32_t FirstWSlice; + uint32_t WSize; + uint32_t MostDetailedMip; + uint32_t MipLevels; + float ResourceMinLODClamp; + } Texture3D; + + struct { + uint32_t MostDetailedMip; + uint32_t MipLevels; + uint32_t FirstArraySlice; + uint32_t ArraySize; + uint32_t PlaneSlice; + float ResourceMinLODClamp; + } TextureCube; + }; +}; + +struct D3D12_UNORDERED_ACCESS_VIEW_DESC { + D3D12_UAV_DIMENSION ViewDimension; + Format Format; + uint32_t Shader4ComponentMapping; + + union { + struct { + uint32_t MipSlice; + } Buffer; + + struct { + uint32_t MipSlice; + uint32_t FirstArraySlice; + uint32_t ArraySize; + uint32_t PlaneSlice; + } Texture2D; + + struct { + uint32_t MipSlice; + uint32_t FirstWSlice; + uint32_t WSize; + } Texture3D; + }; +}; + +struct D3D12_RENDER_TARGET_VIEW_DESC { + D3D12_RTV_DIMENSION ViewDimension; + Format Format; + + union { + struct { + uint32_t MipSlice; + uint32_t FirstArraySlice; + uint32_t ArraySize; + } Texture2D; + + struct { + uint32_t MipSlice; + uint32_t FirstArraySlice; + uint32_t ArraySize; + uint32_t PlaneSlice; + } Texture2DMS; + }; +}; + +struct D3D12_DEPTH_STENCIL_VIEW_DESC { + D3D12_DSV_DIMENSION ViewDimension; + Format Format; + uint32_t MipSlice; + uint32_t FirstArraySlice; + uint32_t ArraySize; + uint32_t PlaneSlice; +}; + +struct D3D12_CONSTANT_BUFFER_VIEW_DESC { + uint64_t BufferLocation; + uint32_t SizeInBytes; +}; + +struct D3D12_SAMPLER_DESC { + D3D12_FILTER Filter; + D3D12_TEXTURE_ADDRESS_MODE AddressU; + D3D12_TEXTURE_ADDRESS_MODE AddressV; + D3D12_TEXTURE_ADDRESS_MODE AddressW; + float MipLODBias; + uint32_t MaxAnisotropy; + D3D12_COMPARISON_FUNC ComparisonFunc; + float BorderColor[4]; + float MinLOD; + float MaxLOD; +}; + +struct InputLayout { + D3D12_INPUT_ELEMENT_DESC* pInputElementDescs = nullptr; + uint32_t NumInputElementDescs = 0; +}; + +struct StreamOutput { + D3D12_SO_DECLARATION_ENTRY* pSODeclaration = nullptr; + uint32_t NumSODeclarationEntries = 0; + uint64_t* pBufferStrides = nullptr; + uint32_t NumBufferStrides = 0; + uint32_t RasterizedStream = 0; +}; + +struct BlendState { + bool AlphaToCoverageEnable = false; + bool IndependentBlendEnable = false; + + struct RenderTargetBlendDesc { + bool BlendEnable = false; + D3D12_BLEND SrcBlend = D3D12_BLEND::ONE; + D3D12_BLEND DestBlend = D3D12_BLEND::ZERO; + D3D12_BLEND_OP BlendOp = D3D12_BLEND_OP::ADD; + D3D12_BLEND SrcBlendAlpha = D3D12_BLEND::ONE; + D3D12_BLEND DestBlendAlpha = D3D12_BLEND::ZERO; + D3D12_BLEND_OP BlendOpAlpha = D3D12_BLEND_OP::ADD; + D3D12_COLOR_WRITE_ENABLE RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE::ALL; + }; + RenderTargetBlendDesc RenderTarget[8]; +}; + +struct RasterizerState { + D3D12_FILL_MODE FillMode = D3D12_FILL_MODE::SOLID; + D3D12_CULL_MODE CullMode = D3D12_CULL_MODE::BACK; + bool FrontCounterClockwise = false; + int32_t DepthBias = 0; + float DepthBiasClamp = 0.0f; + float SlopeScaledDepthBias = 0.0f; + bool DepthClipEnable = true; + bool MultisampleEnable = false; + bool AntialiasedLineEnable = false; + uint32_t ForcedSampleCount = 0; + bool ConservativeRaster = false; +}; + +struct DepthStencilState { + bool DepthEnable = true; + D3D12_DEPTH_WRITE_MASK DepthWriteMask = D3D12_DEPTH_WRITE_MASK::ALL; + D3D12_COMPARISON_FUNC DepthFunc = D3D12_COMPARISON_FUNC::LESS; + bool StencilEnable = false; + uint8_t StencilReadMask = 0xFF; + uint8_t StencilWriteMask = 0xFF; + + struct DepthStencilOpDesc { + D3D12_STENCIL_OP StencilFailOp = D3D12_STENCIL_OP::KEEP; + D3D12_STENCIL_OP StencilDepthFailOp = D3D12_STENCIL_OP::KEEP; + D3D12_STENCIL_OP StencilPassOp = D3D12_STENCIL_OP::KEEP; + D3D12_COMPARISON_FUNC StencilFunc = D3D12_COMPARISON_FUNC::ALWAYS; + }; + DepthStencilOpDesc FrontFace; + DepthStencilOpDesc BackFace; +}; + +enum class D3D12_DEPTH_WRITE_MASK { + ZERO = 0, + ALL = 1 +}; + +enum class D3D12_STENCIL_OP { + KEEP = 1, + ZERO = 2, + REPLACE = 3, + INCR_SAT = 4, + DECR_SAT = 5, + INVERT = 6, + INCR = 7, + DECR = 8 +}; + +struct DXGI_SAMPLE_DESC { + uint32_t Count = 1; + uint32_t Quality = 0; +}; + +struct CachedPSO { + void* pCachedBlob = nullptr; + size_t CachedBlobSizeInBytes = 0; +}; + +enum class D3D12_PIPELINE_STATE_FLAGS { + NONE = 0, + TOOL_DEBUG = 1 +}; + +struct D3D12_GRAPHICS_PIPELINE_STATE_DESC { + InputLayout* InputLayout; + RootSignature* pRootSignature; + Shader* VS; + Shader* HS; + Shader* DS; + Shader* GS; + Shader* PS; + StreamOutput* StreamOutput; + BlendState* BlendState; + uint32_t SampleMask; + RasterizerState* RasterizerState; + DepthStencilState* DepthStencilState; + D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType; + uint32_t NumRenderTargets; + Format RTVFormats[8]; + Format DSVFormat; + DXGI_SAMPLE_DESC SampleDesc; + uint32_t NodeMask; + CachedPSO* cachedPSO; + D3D12_PIPELINE_STATE_FLAGS Flags; +}; + +struct D3D12_COMPUTE_PIPELINE_STATE_DESC { + RootSignature* pRootSignature; + Shader* CS; + uint32_t NodeMask; + CachedPSO* cachedPSO; + D3D12_PIPELINE_STATE_FLAGS Flags; +}; + +class D3D12Device : public IRHIDevice { +public: + D3D12Device(); + virtual ~D3D12Device(); + + GraphicsAPI GetAPI() const override { return GraphicsAPI::Direct3D12; } + const char* GetAPIName() const override { return "Direct3D 12"; } + + bool Initialize() override; + void Shutdown() override; + + ID3D12Device* GetD3D12Device() { return m_device.Get(); } + ID3D12CommandQueue* GetCommandQueue(D3D12_COMMAND_LIST_TYPE type); + + bool CreateCommandQueue(ICommandQueue** queue, const CommandQueueDesc& desc) override; + bool CreateCommandAllocator(ICommandAllocator** allocator) override; + bool CreateCommandList(ICommandList** list, ICommandAllocator* allocator) override; + bool CreateFence(IFence** fence) override; + + bool CreateDescriptorHeap(IDescriptorHeap** heap, const DescriptorHeapDesc& desc) override; + bool CreateQueryHeap(IQueryHeap** heap, const QueryHeapDesc& desc) override; + + bool CreateRootSignature(RootSignature** signature, const RootSignatureDesc& desc) override; + bool CreatePipelineState(PipelineStateObject** pso, const PipelineDesc& desc) override; + + bool CreateSwapChain(ISwapChain** swapChain, const SwapChainDesc& desc, void* windowHandle) override; + + bool CreateRenderTarget(RenderTarget** target, const RenderTargetDesc& desc) override; + bool CreateDepthStencil(DepthStencil** depthStencil, const DepthStencilDesc& desc) override; + + void* GetNativeDevice() const override { return m_device.Get(); } + +private: + ComPtr m_device; + ComPtr m_directQueue; + ComPtr m_computeQueue; + ComPtr m_copyQueue; + + D3D_FEATURE_LEVEL m_featureLevel; + bool m_raytracingSupported; + bool m_meshShadersSupported; +}; + +class D3D12CommandList : public ICommandList { +public: + D3D12CommandList(ID3D12CommandAllocator* allocator); + virtual ~D3D12CommandList(); + + void Reset(ICommandAllocator* allocator) override; + void Close() override; + + void BeginRenderPass(const RenderPassDesc& desc) override; + void EndRenderPass() override; + + void SetPipelineState(PipelineStateObject* pso) override; + void SetRootSignature(RootSignature* signature) override; + + void SetVertexBuffer(uint32_t slot, VertexBuffer* buffer, uint32_t offset = 0) override; + void SetIndexBuffer(IndexBuffer* buffer, uint32_t offset = 0) override; + + void SetDescriptorHeap(IDescriptorHeap* heap) override; + void SetGraphicsDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) override; + void SetComputeDescriptorTable(uint32_t rootParameterIndex, uint64_t baseDescriptor) override; + + void DrawInstanced( + uint32_t vertexCountPerInstance, + uint32_t instanceCount, + uint32_t startVertex, + uint32_t startInstance + ) override; + + void DrawIndexedInstanced( + uint32_t indexCountPerInstance, + uint32_t instanceCount, + uint32_t startIndex, + int32_t baseVertex, + uint32_t startInstance + ) override; + + void Dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ) override; + + void SetViewports(const Viewport* viewports, uint32_t count) override; + void SetScissorRects(const Rect* rects, uint32_t count) override; + + void SetRenderTargets( + const RenderTarget* const* renderTargets, + uint32_t renderTargetCount, + const DepthStencil* depthStencil + ) override; + + void ClearRenderTargetView(const RenderTarget* target, const float color[4]) override; + void ClearDepthStencilView(const DepthStencil* depthStencil, float depth, uint8_t stencil) override; + + void CopyResource(IResource* dst, const IResource* src) override; + void CopyBuffer(IResource* dst, uint64_t dstOffset, const IResource* src, uint64_t srcOffset, uint64_t size) override; + + void ResourceBarrier( + IResource* resource, + ResourceStateFlag stateBefore, + ResourceStateFlag stateAfter + ); + + ID3D12GraphicsCommandList* GetD3D12CommandList() { return m_commandList.Get(); } + +private: + ComPtr m_commandList; + D3D12_PRIMITIVE_TOPOLOGY m_topology = D3D12_PRIMITIVE_TOPOLOGY::UNDEFINED; +}; + +class D3D12DescriptorHeap : public IDescriptorHeap { +public: + D3D12DescriptorHeap(ID3D12DescriptorHeap* heap, DescriptorHeapType type, uint32_t count); + virtual ~D3D12DescriptorHeap(); + + DescriptorHeapType GetType() const override { return m_type; } + uint32_t GetDescriptorCount() const override { return m_descriptorCount; } + + void* GetCPUDescriptorHandle(uint32_t index) const override; + uint64_t GetGPUDescriptorHandle(uint32_t index) const override; + + void SetName(const String& name) override; + + ID3D12DescriptorHeap* GetD3D12DescriptorHeap() { return m_heap.Get(); } + +private: + ComPtr m_heap; + DescriptorHeapType m_type; + uint32_t m_descriptorCount; + uint32_t m_descriptorSize; +}; + +class D3D12RootSignature : public RootSignature { +public: + D3D12RootSignature(); + virtual ~D3D12RootSignature(); + + bool Initialize(const RootSignatureDesc& desc) override; + void SetName(const String& name) override; + + ID3D12RootSignature* GetD3D12RootSignature() { return m_rootSignature.Get(); } + +private: + bool SerializeRootSignature( + const RootSignatureDesc& desc, + std::vector& serializedData + ); + + ComPtr m_rootSignature; +}; + +class D3D12PipelineState : public PipelineStateObject { +public: + D3D12PipelineState(); + virtual ~D3D12PipelineState(); + + bool Initialize(const PipelineDesc& desc); + void SetName(const String& name); + + ID3D12PipelineState* GetD3D12PipelineState() { return m_pipelineState.Get(); } + +private: + ComPtr m_pipelineState; +}; + +class D3D12Fence : public IFence { +public: + D3D12Fence(ID3D12Fence* fence); + virtual ~D3D12Fence(); + + uint64_t GetCompletedValue() const override; + void Signal(uint64_t value) override; + void Wait(uint64_t value) override; + void Wait(uint64_t value, uint64_t timeout) override; + + ID3D12Fence* GetD3D12Fence() { return m_fence.Get(); } + + HANDLE GetEventHandle() { return m_event; } + +private: + ComPtr m_fence; + HANDLE m_event; +}; + +class D3D12QueryHeap : public IQueryHeap { +public: + D3D12QueryHeap(ID3D12QueryHeap* heap, QueryType type, uint32_t count); + virtual ~D3D12QueryHeap(); + + QueryType GetType() const override { return m_type; } + uint32_t GetCount() const override { return m_count; } + + void Begin(ICommandList* cmdList, uint32_t index) override; + void End(ICommandList* cmdList, uint32_t index) override; + + void GetData(uint32_t index, void* data, uint32_t dataSize) override; + + ID3D12QueryHeap* GetD3D12QueryHeap() { return m_queryHeap.Get(); } + +private: + ComPtr m_queryHeap; + QueryType m_type; + uint32_t m_count; +}; + +class D3D12SwapChain : public ISwapChain { +public: + D3D12SwapChain(IDXGISwapChain3* swapChain); + virtual ~D3D12SwapChain(); + + bool Initialize(const SwapChainDesc& desc, void* windowHandle) override; + void Shutdown() override; + + bool Present() override; + bool Resize(uint32_t width, uint32_t height) override; + + uint32_t GetCurrentBufferIndex() const override; + RenderTexture* GetBuffer(uint32_t index) override; + + void SetFullscreen(bool fullscreen) override; + bool IsFullscreen() const override; + + IDXGISwapChain3* GetD3D12SwapChain() { return m_swapChain.Get(); } + +private: + ComPtr m_swapChain; + std::vector m_buffers; + uint32_t m_bufferCount; + bool m_fullscreen; +}; + +} // namespace D3D12 +} // namespace RHI +} // namespace XCEngine + +namespace XCEngine { +namespace Rendering { + +using ICommandList = RHI::ICommandList; +using IBuffer = RHI::IResource; + +enum class BufferUsage { + Default, + Immutable, + Dynamic, + Staging +}; + +enum class MemoryUsage { + Default, + GPU_Only, + CPU_Only, + CPU_GPU +}; + +enum class PassType { + Graphics, + Compute, + Copy, + Raytracing +}; + +enum class LoadAction { + Load, + Clear, + DontCare +}; + +enum class StoreAction { + Store, + Resolve, + StoreAndResolve, + DontCare +}; + +enum class ResolveMode { + None, + Min, + Average, + Sample0, + Sample1, + Sample2, + Sample3, + Sample4, + Sample5, + Sample6, + Sample7 +}; + +enum class ComparisonFunc { + Never, + Less, + Equal, + LessEqual, + Greater, + NotEqual, + GreaterEqual, + Always +}; + +enum class BorderColor { + TransparentBlack, + OpaqueBlack, + OpaqueWhite +}; + +struct IndexType { + static constexpr uint8_t Uint16 = 0; + static constexpr uint8_t Uint32 = 1; +}; + +enum class ResourceState { + Undefined = 0, + Common = 1, + VertexBuffer = 2, + ConstantBuffer = 3, + IndexBuffer = 4, + RenderTarget = 5, + UnorderedAccess = 6, + DepthWrite = 7, + DepthRead = 8, + ShaderResource = 9, + IndirectArgument = 10, + CopyDest = 11, + CopySource = 12, + ResolveDest = 13, + ResolveSource = 14, + Present = 15, + GenericRead = 16 +}; + +struct ResourceDesc { + ResourceType type; + uint32_t width = 1; + uint32_t height = 1; + uint32_t depth = 1; + uint32_t mipLevels = 1; + uint32_t arraySize = 1; + Format format = Format::Unknown; + SampleCount sampleCount = SampleCount::Count1; + ResourceState initialState = ResourceState::Undefined; + bool cpuAccessible = false; + bool randomAccess = false; + + MemoryUsage memoryUsage = MemoryUsage::Default; + + String name; +}; + +class RenderContext { +public: + class GBufferPass; + class LightingPass; + class ShadowPass; + class PostProcessPass; + + static RenderContext* Create(const RenderContextDesc& desc); + static void Destroy(RenderContext* context); + + static RenderContext* GetMain(); + + void Initialize(const RenderContextDesc& desc); + void Shutdown(); + + RHI::IRHIDevice* GetDevice() { return m_device.get(); } + + void BeginFrame(); + void EndFrame(); + + ICommandList* GetMainCommandList() { return m_mainCommandList.get(); } + + void SetRenderTarget(const RenderTarget& target); + void SetViewport(const Viewport& viewport); + void SetScissorRect(const Rect& rect); + + void RenderScene(const SceneRenderDesc& desc); + void ApplyPostProcessing(const PostProcessDesc& desc); + + void CaptureFrame(const String& filePath); + void ToggleDebugView(); + +private: + std::unique_ptr m_device; + std::unique_ptr m_mainCommandList; + std::unique_ptr m_swapChain; + + std::unique_ptr m_gBufferPass; + std::unique_ptr m_lightingPass; + std::unique_ptr m_shadowPass; + std::unique_ptr m_postProcessPass; + + uint32_t m_frameIndex = 0; + uint64_t m_frameCount = 0; + + static RenderContext* s_mainContext; +}; + +struct ResourceGUID { + static constexpr uint64_t INVALID = 0; + + uint64_t value = INVALID; + + bool IsValid() const { return value != INVALID; } + bool operator==(const ResourceGUID& other) const { return value == other.value; } + bool operator!=(const ResourceGUID& other) const { return value != other.value; } + + String ToString() const; + static ResourceGUID FromString(const String& str); + + struct Hash { + size_t operator()(const ResourceGUID& guid) const { + return std::hash{}(guid.value); + } + }; +}; + +class RenderTexture { +public: + uint32_t GetWidth() const { return m_width; } + uint32_t GetHeight() const { return m_height; } + uint32_t GetMipLevels() const { return m_mipLevels; } + Format GetFormat() const { return m_format; } + + void* GetNativeHandle() const { return m_nativeHandle; } + + IShaderResourceView* GetSRV() { return m_srv.get(); } + IRenderTargetView* GetRTV() { return m_rtv.get(); } + IDepthStencilView* GetDSV() { return m_dsv.get(); } + + void* Map(); + void Unmap(); + +private: + uint32_t m_width, m_height; + uint32_t m_mipLevels; + Format m_format; + void* m_nativeHandle = nullptr; + + std::unique_ptr m_srv; + std::unique_ptr m_rtv; + std::unique_ptr m_dsv; +}; + +class RenderBuffer { +public: + uint64_t GetSize() const { return m_size; } + BufferUsage GetUsage() const { return m_usage; } + + void* GetNativeHandle() const { return m_nativeHandle; } + + void SetData(const void* data, uint64_t size, uint64_t offset = 0); + void* Map(); + void Unmap(); + +private: + uint64_t m_size; + BufferUsage m_usage; + void* m_nativeHandle = nullptr; +}; + +} // namespace Rendering +} // namespace XCEngine +``` + +### 4.4 相机组件 + +```cpp +namespace XCEngine { + +class CameraComponent : public Component { +public: + void Awake() override; + void Start() override; + void Update(float deltaTime) override; + + enum class ProjectionType : uint8_t { + Perspective, + Orthographic + }; + + void SetProjectionType(ProjectionType type) { m_projectionType = type; } + ProjectionType GetProjectionType() const { return m_projectionType; } + + void SetFieldOfView(float fov) { m_fieldOfView = fov; } + float GetFieldOfView() const { return m_fieldOfView; } + + void SetOrthographicSize(float size) { m_orthographicSize = size; } + float GetOrthographicSize() const { return m_orthographicSize; } + + void SetNearClipPlane(float near) { m_nearPlane = near; } + float GetNearClipPlane() const { return m_nearPlane; } + + void SetFarClipPlane(float far) { m_farPlane = far; } + float GetFarClipPlane() const { return m_farPlane; } + + void SetViewport(const Rect& rect) { m_viewportRect = rect; } + const Rect& GetViewport() const { return m_viewportRect; } + + void SetCullingMask(int32_t mask) { m_cullingMask = mask; } + int32_t GetCullingMask() const { return m_cullingMask; } + + void SetDepth(float depth) { m_depth = depth; } + float GetDepth() const { return m_depth; } + + Matrix4x4 GetViewMatrix() const; + Matrix4x4 GetProjectionMatrix() const; + Matrix4x4 GetViewProjectionMatrix() const; + + Vector3 ScreenToWorldPoint(const Vector3& screenPoint) const; + Vector3 WorldToScreenPoint(const Vector3& worldPoint) const; + Ray ScreenPointToRay(const Vector2& screenPoint) const; + + Frustum& GetFrustum() { return m_frustum; } + +private: + ProjectionType m_projectionType = ProjectionType::Perspective; + float m_fieldOfView = 60.0f; + float m_orthographicSize = 5.0f; + float m_nearPlane = 0.1f; + float m_farPlane = 1000.0f; + float m_aspectRatio = 16.0f / 9.0f; + Rect m_viewportRect = Rect(0, 0, 1, 1); + float m_depth = 0.0f; + int32_t m_cullingMask = -1; + Frustum m_frustum; +}; + +} // namespace XCEngine +``` + +### 4.5 光照组件 + +```cpp +namespace XCEngine { + +class LightComponent : public Component { +public: + void Awake() override; + void Update(float deltaTime) override; + + enum class LightType : uint8_t { + Directional, + Point, + Spot, + Area + }; + + void SetLightType(LightType type) { m_type = type; } + LightType GetLightType() const { return m_type; } + + void SetColor(const Vector3& color) { m_color = color; } + Vector3 GetColor() const { return m_color; } + + void SetIntensity(float intensity) { m_intensity = intensity; } + float GetIntensity() const { return m_intensity; } + + void SetRange(float range) { m_range = range; } + float GetRange() const { return m_range; } + + void SetSpotAngle(float angle) { m_spotAngle = angle; } + float GetSpotAngle() const { return m_spotAngle; } + + void SetCastShadows(bool cast) { m_castShadows = cast; } + bool GetCastShadows() const { return m_castShadows; } + + void SetShadowResolution(uint32_t resolution) { m_shadowResolution = resolution; } + uint32_t GetShadowResolution() const { return m_shadowResolution; } + + void SetCullingMask(int32_t mask) { m_cullingMask = mask; } + int32_t GetCullingMask() const { return m_cullingMask; } + +private: + LightType m_type = LightType::Point; + Vector3 m_color = Vector3::One(); + float m_intensity = 1.0f; + float m_range = 10.0f; + float m_spotAngle = 30.0f; + float m_penumbraAngle = 5.0f; + bool m_castShadows = true; + uint32_t m_shadowResolution = 1024; + float m_shadowBias = 0.005f; + float m_normalOffsetBias = 0.001f; + float m_nearPlane = 0.1f; + int32_t m_cullingMask = -1; + float m_intensityVariation = 0.0f; + ResourceGUID m_cookieTextureGuid; + float m_cookieSize = 5.0f; +}; + +} // namespace XCEngine +``` + +### 4.6 渲染网格组件 + +```cpp +namespace XCEngine { + +class RenderMeshComponent : public Component { +public: + void Awake() override; + void Start() override; + void Update(float deltaTime) override; + + ResourceGUID GetMesh() const { return m_meshGuid; } + void SetMesh(const ResourceGUID& guid); + + ResourceGUID GetMaterial() const { return m_materialGuid; } + void SetMaterial(const ResourceGUID& guid); + + bool GetCastShadows() const { return m_castShadows; } + void SetCastShadows(bool cast) { m_castShadows = cast; } + + bool GetReceiveShadows() const { return m_receiveShadows; } + void SetReceiveShadows(bool receive) { m_receiveShadows = receive; } + +private: + ResourceGUID m_meshGuid; + ResourceGUID m_materialGuid; + bool m_castShadows = true; + bool m_receiveShadows = true; +}; + +} // namespace XCEngine +``` + +### 4.7 材质系统 + +```cpp +namespace XCEngine { +namespace Rendering { + +enum class ShaderType { + Vertex, + Fragment, + Compute, + Geometry, + Hull, + Domain +}; + +enum class UniformType { + None, + Float, + Float2, + Float3, + Float4, + Int, + Int2, + Int3, + Int4, + Bool, + Sampler2D, + Sampler3D, + SamplerCube, + Sampler2DArray, + Matrix3x3, + Matrix4x4 +}; + +struct UniformDesc { + String name; + UniformType type; + uint32_t arraySize = 1; + uint32_t offset = 0; +}; + +struct ShaderUniformBlock { + String name; + uint32_t bindingSlot = 0; + uint32_t size = 0; + std::vector uniforms; +}; + +class Shader : public IResource { +public: + const String& GetSource() const { return m_source; } + ShaderType GetType() const { return m_type; } + + const std::vector& GetUniformBlocks() const { return m_uniformBlocks; } + const std::vector& GetResources() const { return m_resources; } + + bool HasVariant(const String& variantName) const; + Shader* GetVariant(const HashMap& defines); + + bool IsCompiled() const { return m_compiled; } + const String& GetCompileErrors() const { return m_compileErrors; } + +private: + String m_source; + ShaderType m_type; + bool m_compiled = false; + String m_compileErrors; + + std::vector m_uniformBlocks; + std::vector m_resources; + HashMap> m_variants; +}; + +enum class BlendMode { + Opaque, + Transparent, + Additive, + Multiply, + AlphaTest +}; + +enum class CullMode { + None, + Front, + Back +}; + +enum class ZWriteMode { + On, + Off +}; + +enum class DepthTest { + Never, + Less, + Equal, + LessEqual, + Greater, + NotEqual, + GreaterEqual, + Always +}; + +struct RenderState { + BlendMode blendMode = BlendMode::Opaque; + CullMode cullMode = CullMode::Back; + ZWriteMode zWriteMode = ZWriteMode::On; + DepthTest depthTest = DepthTest::LessEqual; + bool depthClip = true; + bool scissorTest = false; + bool stencilTest = false; + + uint8_t stencilReadMask = 0xFF; + uint8_t stencilWriteMask = 0xFF; + int32_t stencilRef = 0; + + uint32_t colorWriteMask = 0xF; + + bool operator==(const RenderState& other) const; +}; + +struct MaterialPropBlock { + HashMap floatProps; + HashMap intProps; + HashMap matrixProps; + HashMap textureProps; + + void SetFloat(const String& name, float value); + void SetFloat(const String& name, const Vector4& value); + void SetInt(const String& name, int32_t value); + void SetMatrix(const String& name, const Matrix4x4& value); + void SetTexture(const String& name, const ResourceGUID& guid); + + float GetFloat(const String& name, float defaultValue = 0.0f) const; + Vector4 GetFloat4(const String& name, const Vector4& defaultValue = Vector4::Zero()) const; + int32_t GetInt(const String& name, int32_t defaultValue = 0) const; + Matrix4x4 GetMatrix(const String& name, const Matrix4x4& defaultValue = Matrix4x4::Identity()) const; + ResourceGUID GetTexture(const String& name, ResourceGUID defaultValue = ResourceGUID::INVALID) const; +}; + +class Material : public IResource { +public: + Material(); + explicit Material(Shader* shader); + + Shader* GetShader() const { return m_shader; } + void SetShader(Shader* shader); + + const RenderState& GetRenderState() const { return m_renderState; } + void SetRenderState(const RenderState& state) { m_renderState = state; } + + MaterialPropBlock& GetPropBlock() { return m_props; } + const MaterialPropBlock& GetPropBlock() const { return m_props; } + + int32_t GetRenderQueue() const { return m_renderQueue; } + void SetRenderQueue(int32_t queue) { m_renderQueue = queue; } + + void SetFloat(const String& name, float value); + void SetFloat(const String& name, const Vector4& value); + void SetInt(const String& name, int32_t value); + void SetTexture(const String& name, const ResourceGUID& guid); + + float GetFloat(const String& name, float defaultValue = 0.0f) const; + int32_t GetInt(const String& name, int32_t defaultValue = 0) const; + ResourceGUID GetTexture(const String& name) const; + + bool IsInstanced() const { return m_instanced; } + void SetInstanced(bool instanced) { m_instanced = instanced; } + +private: + Shader* m_shader = nullptr; + RenderState m_renderState; + MaterialPropBlock m_props; + int32_t m_renderQueue = 0; + bool m_instanced = false; +}; + +class MaterialManager { +public: + static MaterialManager& Get(); + + void Initialize(); + void Shutdown(); + + Material* CreateMaterial(Shader* shader); + Material* GetMaterial(const ResourceGUID& guid) const; + void DestroyMaterial(Material* material); + + Material* FindMaterialByName(const String& name) const; + +private: + HashMap> m_materials; + uint64_t m_nextId = 1; +}; + +class MaterialPropertyBlock { +public: + MaterialPropertyBlock(); + ~MaterialPropertyBlock(); + + void Clear(); + + void SetFloat(const String& name, float value); + void SetVector(const String& name, const Vector4& value); + void SetColor(const String& name, const Color& value); + void SetMatrix(const String& name, const Matrix4x4& matrix); + void SetTexture(const String& name, Texture* texture); + + bool HasProperty(const String& name) const; + float GetFloat(const String& name, float defaultValue = 0.0f) const; + Vector4 GetVector(const String& name, const Vector4& defaultValue = Vector4::Zero()) const; + Color GetColor(const String& name, const Color& defaultValue = Color::White()) const; + Matrix4x4 GetMatrix(const String& name, const Matrix4x4& defaultValue = Matrix4x4::Identity()) const; + Texture* GetTexture(const String& name) const; + + bool IsEmpty() const { return m_properties.empty(); } + size_t GetPropertyCount() const { return m_properties.size(); } + + void ApplyToMaterial(Material* material) const; + void CopyFrom(const MaterialPropertyBlock& other); + +private: + struct PropertyValue { + enum class Type { Float, Vector, Matrix, Texture }; + Type type; + union { + float floatValue; + Vector4 vectorValue; + Matrix4x4 matrixValue; + Texture* textureValue; + }; + }; + HashMap m_properties; +}; + +class RenderSettings { +public: + static RenderSettings& Get(); + + void Load(); + void Save(); + + enum class AmbientMode { + Skybox, + Trilight, + Flat, + Custom + }; + + AmbientMode GetAmbientMode() const { return m_ambientMode; } + void SetAmbientMode(AmbientMode mode) { m_ambientMode = mode; } + + Color GetAmbientSkyColor() const { return m_ambientSkyColor; } + void SetAmbientSkyColor(const Color& color) { m_ambientSkyColor = color; } + + Color GetAmbientEquatorColor() const { return m_ambientEquatorColor; } + void SetAmbientEquatorColor(const Color& color) { m_ambientEquatorColor = color; } + + Color GetAmbientGroundColor() const { return m_ambientGroundColor; } + void SetAmbientGroundColor(const Color& color) { m_ambientGroundColor = color; } + + float GetAmbientIntensity() const { return m_ambientIntensity; } + void SetAmbientIntensity(float intensity) { m_ambientIntensity = intensity; } + + bool GetFogEnabled() const { return m_fogEnabled; } + void SetFogEnabled(bool enabled) { m_fogEnabled = enabled; } + + enum class FogMode { + Linear, + Exponential, + ExponentialSquared + }; + + FogMode GetFogMode() const { return m_fogMode; } + void SetFogMode(FogMode mode) { m_fogMode = mode; } + + Color GetFogColor() const { return m_fogColor; } + void SetFogColor(const Color& color) { m_fogColor = color; } + + float GetFogDensity() const { return m_fogDensity; } + void SetFogDensity(float density) { m_fogDensity = density; } + + float GetFogStartDistance() const { return m_fogStartDistance; } + void SetFogStartDistance(float distance) { m_fogStartDistance = distance; } + + float GetFogEndDistance() const { return m_fogEndDistance; } + void SetFogEndDistance(float distance) { m_fogEndDistance = distance; } + + float GetShadowDistance() const { return m_shadowDistance; } + void SetShadowDistance(float distance) { m_shadowDistance = distance; } + + uint32_t GetShadowCascadeCount() const { return m_shadowCascadeCount; } + void SetShadowCascadeCount(uint32_t count) { m_shadowCascadeCount = count; } + + float GetShadowResolution() const { return m_shadowResolution; } + void SetShadowResolution(float resolution) { m_shadowResolution = resolution; } + + Texture* GetSkybox() const { return m_skybox; } + void SetSkybox(Texture* skybox) { m_skybox = skybox; } + +private: + RenderSettings() = default; + + AmbientMode m_ambientMode = AmbientMode::Skybox; + Color m_ambientSkyColor = Color{0.5f, 0.5f, 0.5f, 1.0f}; + Color m_ambientEquatorColor = Color{0.2f, 0.2f, 0.2f, 1.0f}; + Color m_ambientGroundColor = Color{0.1f, 0.1f, 0.1f, 1.0f}; + float m_ambientIntensity = 1.0f; + + bool m_fogEnabled = false; + FogMode m_fogMode = FogMode::Linear; + Color m_fogColor = Color{0.5f, 0.5f, 0.5f, 1.0f}; + float m_fogDensity = 0.01f; + float m_fogStartDistance = 10.0f; + float m_fogEndDistance = 100.0f; + + float m_shadowDistance = 150.0f; + uint32_t m_shadowCascadeCount = 4; + float m_shadowResolution = 1024.0f; + + Texture* m_skybox = nullptr; +}; + +class GraphicsSettings { +public: + static GraphicsSettings& Get(); + + void Load(); + void Save(); + + enum class ColorSpace { + Gamma, + Linear + }; + + ColorSpace GetColorSpace() const { return m_colorSpace; } + void SetColorSpace(ColorSpace space) { m_colorSpace = space; } + + enum class HDRSetting { + Off, + On, + Auto + }; + + HDRSetting GetHDR() const { return m_hdr; } + void SetHDR(HDRSetting hdr) { m_hdr = hdr; } + + uint32_t GetMSAASamples() const { return m_msaaSamples; } + void SetMSAASamples(uint32_t samples) { m_msaaSamples = samples; } + + bool GetRealtimeReflectionProbes() const { return m_realtimeReflectionProbes; } + void SetRealtimeReflectionProbes(bool enabled) { m_realtimeReflectionProbes = enabled; } + + float GetLODBias() const { return m_lodBias; } + void SetLODBias(float bias) { m_lodBias = bias; } + + int GetMaximumLODLevel() const { return m_maximumLODLevel; } + void SetMaximumLODLevel(int level) { m_maximumLODLevel = level; } + + enum class ShaderQuality { + Low, + Medium, + High + }; + + ShaderQuality GetShaderQuality() const { return m_shaderQuality; } + void SetShaderQuality(ShaderQuality quality) { m_shaderQuality = quality; } + +private: + GraphicsSettings() = default; + + ColorSpace m_colorSpace = ColorSpace::Linear; + HDRSetting m_hdr = HDRSetting::Auto; + uint32_t m_msaaSamples = 4; + bool m_realtimeReflectionProbes = true; + float m_lodBias = 1.0f; + int m_maximumLODLevel = -1; + ShaderQuality m_shaderQuality = ShaderQuality::High; +}; + +} // namespace Rendering +} // namespace XCEngine +``` + +### 4.8 渲染管线 + +```cpp +namespace XCEngine { +namespace Rendering { + +enum class RenderPipelineType { + Forward, + Deferred, + Hybrid, + Custom +}; + +struct RenderPipelineDesc { + RenderPipelineType type = RenderPipelineType::Forward; + uint32_t maxLights = 16; + bool shadowEnabled = true; + uint32_t shadowMapSize = 2048; + bool ssaoEnabled = false; + bool bloomEnabled = false; + bool toneMappingEnabled = true; + String toneMappingCurve = "ACES"; +}; + +struct RenderItem { + ResourceGUID meshGuid; + Material* material = nullptr; + Matrix4x4 worldMatrix; + uint32_t instanceId = 0; + int32_t renderQueue = 0; + uint32_t subMeshIndex = 0; + uint32_t lightingHash = 0; + + float GetDistanceSq(const Vector3& cameraPos) const; + bool operator<(const RenderItem& other) const; +}; + +struct CullingParams { + Vector3 position; + float sphereCulling; + + Matrix4x4 viewMatrix; + Matrix4x4 projectionMatrix; + + float nearClipPlane; + float farClipPlane; + + Rect viewport; + + int32_t cullingPlaneFlags; + int32_t cullingMask; + int32_t ortho; + + float shadowDistance; + float shadowNearPlaneDistance; + + bool isOrthographic; + bool cullDynamicObjects; + int32_t LODStripping; + int32_t forceCullingMode; + int32_t maximumLODLevel; + int32_t minimumLODLevel; +}; + +struct CullingResults { + struct VisibleObject { + uint64_t instanceID; + int32_t referenceID; + + Matrix4x4 localToWorldMatrix; + Matrix4x4 localToWorldMatrixPrevious; + + uint64_t staticBatchRootID; + + uint32_t subMeshIndex; + + Vector4 lightmapScaleOffset; + uint32_t lightmapIndex; + + bool staticShadowCaster; + bool motionVectors; + }; + + std::vector visibleRenderers; + + struct LightData { + uint64_t lightID; + int32_t uniqueID; + + Vector3 position; + Vector3 color; + Vector3 forward; + + float range; + float intensity; + float spotAngle; + + int32_t lightType; + int32_t renderMode; + + bool enabled; + bool shadowsEnabled; + + int32_t cullingMask; + + Matrix4x4 viewMatrix; + Matrix4x4 projectionMatrix; + }; + + std::vector visibleLights; + + Frustum frustumPlanes[2]; +}; + +class CullingSystem { +public: + static CullingSystem& Get(); + + void Initialize(); + void Shutdown(); + + bool PerformCulling( + const CullingParams& params, + CullingResults& results, + Scene* scene + ); + + void ComputeFrustumPlanes( + const Matrix4x4& viewMatrix, + const Matrix4x4& projectionMatrix, + Frustum& frustum + ); + +private: + std::vector m_visibleRenderers; + Frustum m_frustum; + std::vector m_cullingPlanes; +}; + +class ScriptableRenderContext { +public: + ScriptableRenderContext(); + ~ScriptableRenderContext(); + + void SetRenderTarget( + RenderTargetIdentifier colorTarget, + RenderTargetIdentifier depthTarget + ); + + void PushDebugGroup(const char* name); + void PopDebugGroup(); + + void BeginSample(const char* name); + void EndSample(const char* name); + + void DrawRenderer( + RenderItem* renderers, + size_t count, + Material* material, + int passIndex + ); + + void ExecuteAndPresent(); + + void Submit(); + +private: + CommandBuffer* m_commandBuffer; + RenderTargetIdentifier m_activeColorTarget; + RenderTargetIdentifier m_activeDepthTarget; +}; + +class LightManager { +public: + static LightManager& Get(); + + void Initialize(); + void Shutdown(); + + void UpdateLights( + Scene* scene, + CameraComponent* camera, + CullingResults& cullingResults + ); + + void GetMainLight(LightData& light); + void GetVisibleLights(std::vector& lights); + + int GetVisibleLightCount() const { return m_visibleLights.size(); } + bool HasShadows() const { return m_shadowsEnabled; } + + void SetShadowDistance(float distance) { m_shadowDistance = distance; } + float GetShadowDistance() const { return m_shadowDistance; } + +private: + std::vector m_visibleLights; + int m_mainLightIndex = -1; + + float m_shadowDistance = 50.0f; + bool m_shadowsEnabled = true; +}; + +class ShadowAtlas { +public: + ShadowAtlas(); + ~ShadowAtlas(); + + void Initialize(int width, int height); + void Shutdown(); + + void Update( + const std::vector& lights, + CullingResults& cullingResults + ); + + RenderTexture* GetTexture() const { return m_texture.get(); } + +private: + struct ShadowSlice { + int x, y; + int width, height; + bool allocated; + LightData* light; + }; + + std::unique_ptr m_texture; + int m_width = 0; + int m_height = 0; + + std::vector m_slices; +}; + +class Renderer { +public: + Renderer(); + ~Renderer(); + + void Initialize(); + void Shutdown(); + + void Render( + ScriptableRenderContext& context, + CameraComponent* camera, + CullingResults& cullingResults, + RenderQueue& renderQueue + ); + + void RenderOpaque( + ScriptableRenderContext& context, + CullingResults& cullingResults, + RenderQueue& renderQueue + ); + + void RenderTransparent( + ScriptableRenderContext& context, + CullingResults& cullingResults, + RenderQueue& renderQueue + ); + + void RenderShadowCasters( + ScriptableRenderContext& context, + CullingResults& cullingResults + ); + + void SortRenderers(RenderQueue& renderQueue); + +private: + void PrepareRenderQueueEntries( + RenderQueue& renderQueue, + CullingResults& cullingResults + ); + + Material* m_defaultMaterial = nullptr; +}; + +class RenderQueue { +public: + void Clear(); + void Sort(); + + void Add(const RenderItem& item); + void AddRange(const RenderItem* items, size_t count); + + const std::vector& GetOpaque() const { return m_opaque; } + const std::vector& GetTransparent() const { return m_transparent; } + const std::vector& GetAlphaTest() const { return m_alphaTest; } + + size_t GetOpaqueCount() const { return m_opaque.size(); } + size_t GetTransparentCount() const { return m_transparent.size(); } + size_t GetAlphaTestCount() const { return m_alphaTest.size(); } + +private: + std::vector m_opaque; + std::vector m_transparent; + std::vector m_alphaTest; +}; + +struct CameraData { + Matrix4x4 viewMatrix; + Matrix4x4 projectionMatrix; + Matrix4x4 viewProjectionMatrix; + Vector3 position; + Vector3 forward; + Vector3 up; + Vector3 right; + float nearPlane; + float farPlane; + float fov; + float aspectRatio; + Rect viewport; + bool isOrthographic; +}; + +struct RenderContextData { + CameraData camera; + std::vector lights; + std::vector visibleLights; + float deltaTime; + float time; + uint32_t frameIndex; + uint64_t frameCount; +}; + +class RenderPipeline { +public: + virtual ~RenderPipeline() = default; + + virtual void Initialize(const RenderPipelineDesc& desc); + virtual void Shutdown(); + + virtual void Prepare(RenderContextData& context); + virtual void Execute(RHI::ICommandList* cmdList, RenderContextData& context); + virtual void Present(); + + RenderQueue& GetRenderQueue() { return m_renderQueue; } + const RenderQueue& GetRenderQueue() const { return m_renderQueue; } + + RenderTexture* GetColorTarget() const { return m_colorTarget.get(); } + RenderTexture* GetDepthTarget() const { return m_depthTarget.get(); } + + virtual void Resize(uint32_t width, uint32_t height); + +protected: + virtual void CollectRenderItems(Scene* scene, CameraComponent* camera); + virtual void SortRenderItems(); + virtual void SetupLights(Scene* scene, CameraComponent* camera); + + RenderPipelineDesc m_desc; + RenderQueue m_renderQueue; + + std::unique_ptr m_colorTarget; + std::unique_ptr m_depthTarget; + + std::vector m_mainLightData; + std::vector m_additionalLightData; +}; + +class ForwardPipeline : public RenderPipeline { +public: + void Initialize(const RenderPipelineDesc& desc) override; + void Execute(RHI::ICommandList* cmdList, RenderContextData& context) override; + +private: + void RenderOpaque(RHI::ICommandList* cmdList, RenderContextData& context); + void RenderTransparent(RHI::ICommandList* cmdList, RenderContextData& context); + void RenderAlphaTest(RHI::ICommandList* cmdList, RenderContextData& context); + void RenderShadowMaps(RHI::ICommandList* cmdList); + void RenderLighting(RHI::ICommandList* cmdList, RenderContextData& context); +}; + +class DeferredPipeline : public RenderPipeline { +public: + void Initialize(const RenderPipelineDesc& desc) override; + void Execute(RHI::ICommandList* cmdList, RenderContextData& context) override; + +private: + void RenderGBuffer(RHI::ICommandList* cmdList); + void RenderDeferredLighting(RHI::ICommandList* cmdList); + void RenderDeferredShading(RHI::ICommandList* cmdList); + + std::unique_ptr m_gBufferAlbedo; + std::unique_ptr m_gBufferNormal; + std::unique_ptr m_gBufferMetallicRoughness; + std::unique_ptr m_gBufferDepth; +}; + +class RenderPipelineManager { +public: + static RenderPipelineManager& Get(); + + void Initialize(const RenderPipelineDesc& desc); + void Shutdown(); + + RenderPipeline* GetPipeline() const { return m_pipeline.get(); } + + void SetPipeline(std::unique_ptr pipeline); + void CreatePipeline(RenderPipelineType type); + + void Resize(uint32_t width, uint32_t height); + +private: + std::unique_ptr m_pipeline; + RenderPipelineDesc m_desc; +}; + +} // namespace Rendering +} // namespace XCEngine +``` + +--- + +## 第五章 目录结构(与 Unity 引擎目录结构一致) + +``` +XCVolumeRenderer/ +├── engine/ # 引擎核心库(静态库) +│ ├── CMakeLists.txt +│ ├── include/ +│ │ └── XCEngine/ +│ │ ├── Core/ # 核心基础 +│ │ │ ├── Assert.h +│ │ │ ├── Event.h +│ │ │ ├── TypeTraits.h +│ │ │ └── UniquePtr.h +│ │ ├── Math/ # 数学库(与 Unity Mathf 对应) +│ │ │ ├── Vector2.h +│ │ │ ├── Vector3.h +│ │ │ ├── Vector4.h +│ │ │ ├── Matrix3.h +│ │ │ ├── Matrix4.h +│ │ │ ├── Quaternion.h +│ │ │ ├── Transform.h +│ │ │ ├── Color.h +│ │ │ ├── Ray.h +│ │ │ ├── Plane.h +│ │ │ ├── Sphere.h +│ │ │ ├── Box.h +│ │ │ ├── Bounds.h +│ │ │ └── Frustum.h +│ │ ├── Containers/ # 容器(与 Unity Collections 对应) +│ │ │ ├── Array.h +│ │ │ ├── String.h +│ │ │ ├── StringView.h +│ │ │ └── HashMap.h +│ │ ├── Memory/ # 内存管理 +│ │ │ ├── Allocator.h +│ │ │ ├── LinearAllocator.h +│ │ │ ├── PoolAllocator.h +│ │ │ └── ProxyAllocator.h +│ │ ├── Threading/ # 线程系统 +│ │ │ ├── Thread.h +│ │ │ ├── Mutex.h +│ │ │ ├── SpinLock.h +│ │ │ ├── ReadWriteLock.h +│ │ │ ├── TaskSystem.h +│ │ │ └── Atomic.h +│ │ ├── Debug/ # 调试系统 +│ │ │ ├── Logger.h +│ │ │ ├── Profiler.h +│ │ │ └── LogSink.h +│ │ ├── Components/ # 组件系统(与 Unity Component 对应) +│ │ │ ├── GameObject.h +│ │ │ ├── Component.h +│ │ │ ├── ComponentTypeRegistry.h +│ │ │ ├── TransformComponent.h +│ │ │ ├── RenderMeshComponent.h +│ │ │ ├── LightComponent.h +│ │ │ └── CameraComponent.h +│ │ ├── Scene/ # 场景系统(与 Unity SceneManager 对应) +│ │ │ ├── Scene.h +│ │ │ ├── SceneManager.h +│ │ │ └── GameObjectBuilder.h +│ │ ├── Renderer/ # 渲染系统(核心,与 Unity Graphics/Shader 对应) +│ │ │ ├── Device.h # 设备抽象 +│ │ │ ├── Context.h # 渲染上下文 +│ │ │ ├── SwapChain.h # 交换链 +│ │ │ ├── Buffer.h # 缓冲区 +│ │ │ ├── Texture.h # 纹理 +│ │ │ ├── Shader.h # Shader +│ │ │ ├── Material.h # 材质 +│ │ │ ├── Pipeline.h # 渲染管线 +│ │ │ ├── RenderPass.h # 渲染通道 +│ │ │ ├── CommandList.h # 命令列表 +│ │ │ ├── RenderQueue.h # 渲染队列 +│ │ │ ├── RenderPipeline.h # 渲染管线基类 +│ │ │ ├── CullingSystem.h # 剔除系统 +│ │ │ ├── Renderer.h # 渲染器 +│ │ │ ├── LightManager.h # 光照管理器 +│ │ │ ├── ShadowAtlas.h # 阴影图集 +│ │ │ └── RenderModule.h # 渲染模块 +│ │ ├── RHI/ # 渲染硬件抽象层(与 Unity GraphicsDevice 对应) +│ │ │ ├── RHISystem.h # RHI 系统入口 +│ │ │ ├── RHIDevice.h # 抽象设备接口 +│ │ │ ├── CommandQueue.h # 命令队列 +│ │ │ ├── CommandList.h # 命令列表 +│ │ │ ├── CommandAllocator.h # 命令分配器 +│ │ │ ├── Fence.h # 同步围栏 +│ │ │ ├── DescriptorHeap.h # 描述符堆 +│ │ │ ├── QueryHeap.h # 查询堆 +│ │ │ ├── RootSignature.h # 根签名 +│ │ │ ├── PipelineState.h # 管线状态 +│ │ │ ├── Sampler.h # 采样器 +│ │ │ └── SwapChain.h # 交换链 +│ │ ├── RHI/D3D12/ # D3D12 后端实现 +│ │ │ ├── D3D12Device.h +│ │ │ ├── D3D12CommandList.h +│ │ │ ├── D3D12CommandQueue.h +│ │ │ ├── D3D12DescriptorHeap.h +│ │ │ ├── D3D12RootSignature.h +│ │ │ ├── D3D12PipelineState.h +│ │ │ ├── D3D12Fence.h +│ │ │ ├── D3D12QueryHeap.h +│ │ │ ├── D3D12SwapChain.h +│ │ │ ├── D3D12Texture.h +│ │ │ └── D3D12Buffer.h +│ │ └── XCEngine.h # 主头文件 +│ ├── src/ +│ │ ├── Core/ +│ │ ├── Math/ +│ │ ├── Components/ +│ │ ├── Scene/ +│ │ ├── Renderer/ +│ │ ├── RHI/ +│ │ │ ├── CMakeLists.txt +│ │ │ └── D3D12/ +│ │ └── ... +│ └── third_party/ +│ ├── DirectX/ # DirectX SDK +│ ├── stb/ # stb 图像库 +│ ├── json/ # json 解析库 +│ └── NanoVDB/ # NanoVDB 体积渲染库 +│ +├── runtime/ # 游戏运行时(独立可执行文件) +│ ├── CMakeLists.txt +│ ├── src/ +│ │ ├── GameMain.cpp +│ │ ├── EntryPoint.cpp +│ │ └── Application.cpp +│ └── resources/ +│ ├── Shaders/ +│ ├── Models/ +│ ├── Textures/ +│ └── Volumes/ +│ +├── tools/ # 工具链 +│ ├── ShaderCompiler/ # 着色器编译器 +│ │ ├── ShaderCompiler.h +│ │ └── ShaderCompileOptions.h +│ ├── BuildTool/ # 构建打包工具 +│ └── AssetProcessor/ # 资源处理工具 +│ +├── content/ # 资源内容 +│ ├── Assets/ # 资源文件夹 +│ ├── Scenes/ # 场景文件 +│ └── Packages/ # 资源包 +│ +└── projects/ # 项目文件夹 + └── .. + +# Unity 引擎目录结构对照 +# Unity/Editor/Data/Resources/ +# Unity/Editor/Data/Modules/ +# Unity/Editor/Data/Tools/ +``` + +--- + +## 附录:待扩展功能 + +以下功能将在后续迭代中添加: + +1. **物理系统** - RigidBodyComponent, ColliderComponent, PhysicsWorld +2. **音频系统** - AudioSourceComponent, AudioListenerComponent, AudioEngine +3. **动画系统** - AnimatorComponent, AnimationClip, Skeleton +4. **粒子系统** - ParticleSystemComponent, GPUParticles +5. **UI系统** - CanvasComponent, ImageComponent, TextComponent, ButtonComponent +6. **网络系统** - NetworkIdentityComponent, NetworkTransformComponent +7. **完整编辑器** - HierarchyPanel, InspectorPanel, SceneViewPanel diff --git a/docs/plan/XCGameEngine架构设计.md b/docs/plan/XCGameEngine架构设计.md new file mode 100644 index 0000000..b505f2c --- /dev/null +++ b/docs/plan/XCGameEngine架构设计.md @@ -0,0 +1,6025 @@ +# XCEngine - 仿Unity引擎架构设计文档 + +> **⚠️ 重要声明(严禁修改!)** +> 下文出现矛盾时永远以开头声明为准!!!!!!!! +> 本架构**1:1参考传统Unity引擎架构**(GameObject + MonoBehaviour模式),**不是Unity DOTS**! +> +> - 组件是**类**(引用类型),包含数据和行为 +> - 实体是GameObject容器 +> - 系统是OOP风格的类 +> - 不是纯数据组件 + 纯函数系统的DOTS模式 +> - 不是SoA内存布局(**除粒子系统性能关键路径外**) +> - 不要被"ECS"这个词误导,这里是传统Unity的Component模式 +> - TransformComponent继承自Component,与Unity的GetComponent\() API行为一致 + +--- + +## 文档信息 + +- **版本**: 1.0 +- **日期**: 2026-03-12 +- **状态**: 架构设计文档 +- **目标**: 构建类Unity的专业游戏引擎 + +--- + +## 第一章 整体架构概览 + +### 1.1 架构设计原则 + +本引擎采用**分层架构**结合**模块化设计**,遵循以下核心原则: + +1. **关注点分离 (Separation of Concerns)**: 各系统独立演化,通过明确定义的接口通信 +2. **依赖倒置 (Dependency Inversion)**: 上层模块依赖抽象接口,不依赖具体实现 +3. **开闭原则 (Open-Closed)**: 对扩展开放,对修改封闭 +4. **单一职责 (Single Responsibility)**: 每个模块只负责一项职责 +5. **数据驱动 (Data-Driven)**: 引擎行为由数据(组件、资源、配置)驱动 +6. **组件化架构**: 采用类Unity的组件模式,组件挂载在实体上 +7. **渲染抽象**: 跨 API 的渲染接口,便于多平台支持 + +### 1.2 整体架构图 + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ XCGameEngine │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────────┐│ +│ │ Editor │ │ Runtime │ │ Toolchain ││ +│ │ (编辑器) │ │ (运行时) │ │ (工具链) ││ +│ ├─────────────────┤ ├─────────────────┤ ├─────────────────────────┤│ +│ │ • UI Framework │ │ • Game Loop │ │ • Asset Processor ││ +│ │ • Scene View │ │ • Component Update │ │ • Shader Compiler ││ +│ │ • Inspector │ │ • Physics Sim │ │ • Mesh Optimizer ││ +│ │ • Hierarchy │ │ • Audio Engine │ │ • Texture Compressor ││ +│ │ • Project │ │ • Script VM │ │ • Build Pipeline ││ +│ │ • Console │ │ • Networking │ │ • Profiler ││ +│ └────────┬────────┘ └────────┬────────┘ └────────────┬────────────┘│ +│ │ │ │ │ +│ └───────────────────────┼──────────────────────────┘ │ +│ │ │ +│ ┌────────────────────────────────▼───────────────────────────────────────┐ │ +│ │ Engine Core │ │ +│ ├────────────────────────────────────────────────────────────────────────┤ │ +│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐│ │ +│ │ │ Renderer │ │ Scene │ │ Resource │ │ Components ││ │ +│ │ │ (渲染) │ │ (场景) │ │ (资源) │ │ (组件系统) ││ │ +│ │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘│ │ +│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐│ │ +│ │ │ Physics │ │ Audio │ │ Script │ │ Math ││ │ +│ │ │ (物理) │ │ (音频) │ │ (脚本) │ │ (数学) ││ │ +│ │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘│ │ +│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐│ │ +│ │ │ Memory │ │ Thread │ │ Network │ │ File ││ │ +│ │ │ (内存) │ │ (线程) │ │ (网络) │ │ (文件) ││ │ +│ │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘│ │ +│ └───────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌────────────────────────────────▼───────────────────────────────────────┐ │ +│ │ Platform Layer │ │ +│ ├────────────────────────────────────────────────────────────────────────┤ │ +│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────────────┐ │ │ +│ │ │ D3D12 │ │ Vulkan │ │ Metal │ │ OpenGL │ │ │ +│ │ └─────────┘ └─────────┘ └─────────┘ └─────────────────┘ │ │ +│ └───────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 1.3 目录结构设计 + +``` +XCVolumeRenderer/ +├── engine/ # 引擎核心库(静态库) +│ ├── CMakeLists.txt +│ ├── include/ +│ │ └── XCGameEngine/ +│ │ ├── Core/ # 核心基础 +│ │ │ ├── Assert.h +│ │ │ ├── Enum.h +│ │ │ ├── Flags.h +│ │ │ ├── TypeTraits.h +│ │ │ ├── Variant.h +│ │ │ └── UniquePtr.h +│ │ ├── Math/ # 数学库 +│ │ │ ├── Vector2.h +│ │ │ ├── Vector3.h +│ │ │ ├── Vector4.h +│ │ │ ├── Matrix2.h +│ │ │ ├── Matrix3.h +│ │ │ ├── Matrix4.h +│ │ │ ├── Quaternion.h +│ │ │ ├── Transform.h +│ │ │ ├── Color.h +│ │ │ ├── MathUtils.h +│ │ │ ├── Ray.h +│ │ │ ├── Plane.h +│ │ │ ├── Sphere.h +│ │ │ ├── Box.h +│ │ │ └── Frustum.h +│ │ ├── Containers/ # 容器 +│ │ │ ├── Array.h +│ │ │ ├── FixedArray.h +│ │ │ ├── Vector.h +│ │ │ ├── Map.h +│ │ │ ├── Set.h +│ │ │ ├── HashMap.h +│ │ │ ├── String.h +│ │ │ └── RingBuffer.h +│ │ ├── Memory/ # 内存管理 +│ │ │ ├── Allocator.h +│ │ │ ├── StackAllocator.h +│ │ │ ├── PoolAllocator.h +│ │ │ ├── FreeListAllocator.h +│ │ │ ├── ProxyAllocator.h +│ │ │ └── MemoryUtils.h +│ │ ├── Threading/ # 线程 +│ │ │ ├── Thread.h +│ │ │ ├── Mutex.h +│ │ │ ├── RWLock.h +│ │ │ ├── Semaphore.h +│ │ │ ├── ThreadPool.h +│ │ │ ├── TaskSystem.h +│ │ │ ├── SpinLock.h +│ │ │ └── Atomic.h +│ │ ├── IO/ # 文件IO +│ │ │ ├── FileSystem.h +│ │ │ ├── Path.h +│ │ │ ├── Stream.h +│ │ │ ├── FileReader.h +│ │ │ ├── FileWriter.h +│ │ │ ├── Archive.h +│ │ │ └── Compression.h +│ │ ├── Debug/ # 调试 +│ │ │ ├── Logger.h +│ │ │ ├── Profiler.h +│ │ │ ├── DebugDraw.h +│ │ │ ├── Assertion.h +│ │ │ └── Traces.h +│ │ ├── Components/ # 组件系统(类Unity GameObject模式) +│ │ │ ├── GameObject.h # 游戏对象 +│ │ │ ├── Component.h # 组件基类 +│ │ │ └── System.h # 系统基类 +│ │ ├── Scene/ # 场景系统 +│ │ │ ├── Scene.h +│ │ │ ├── SceneLoader.h +│ │ │ ├── SceneSerializer.h +│ │ │ ├── SubScene.h +│ │ │ └── SceneManager.h +│ │ ├── Renderer/ # 渲染系统 +│ │ │ ├── ForwardDeclarations.h +│ │ │ ├── Device.h +│ │ │ ├── Context.h +│ │ │ ├── SwapChain.h +│ │ │ ├── Buffer.h +│ │ │ ├── Texture.h +│ │ │ ├── Shader.h +│ │ │ ├── Pipeline.h +│ │ │ ├── RenderPass.h +│ │ │ ├── RenderTarget.h +│ │ │ ├── CommandList.h +│ │ │ ├── CommandQueue.h +│ │ │ ├── Descriptor.h +│ │ │ ├── Fence.h +│ │ │ ├── QueryHeap.h +│ │ │ ├── GpuResource.h +│ │ │ ├── GpuAllocator.h +│ │ │ ├── GpuEvent.h +│ │ │ ├── RenderModule.h +│ │ │ ├── RenderGraph.h +│ │ │ ├── Light.h +│ │ │ ├── Camera.h +│ │ │ ├── Material.h +│ │ │ ├── Mesh.h +│ │ │ ├── Skybox.h +│ │ │ ├── DebugRenderer.h +│ │ │ └── PostProcess.h +│ │ ├── Resources/ # 资源系统 +│ │ │ ├── Resource.h +│ │ │ ├── ResourceManager.h +│ │ │ ├── ResourceLoader.h +│ │ │ ├── ResourceCache.h +│ │ │ ├── AssetDatabase.h +│ │ │ ├── ImportSettings.h +│ │ │ ├── ResourceCooker.h +│ │ │ └── Bundle.h +│ │ ├── Physics/ # 物理系统 +│ │ │ ├── PhysicsWorld.h +│ │ │ ├── RigidBody.h +│ │ │ ├── Collider.h +│ │ │ ├── Joint.h +│ │ │ ├── CharacterController.h +│ │ │ ├── Trigger.h +│ │ │ ├── Raycast.h +│ │ │ ├── ForceField.h +│ │ │ └── PhysicsMaterial.h +│ │ ├── Audio/ # 音频系统 +│ │ │ ├── AudioEngine.h +│ │ │ ├── AudioSource.h +│ │ │ ├── AudioListener.h +│ │ │ ├── AudioClip.h +│ │ │ ├── AudioMixer.h +│ │ │ ├── AudioEffect.h +│ │ │ └── AudioBanks.h +│ │ ├── Scripting/ # 脚本系统 +│ │ │ ├── ScriptEngine.h +│ │ │ ├── ScriptClass.h +│ │ │ ├── ScriptObject.h +│ │ │ ├── ScriptMethod.h +│ │ │ ├── MonoBridge.h +│ │ │ ├── LuaBridge.h +│ │ │ └── AngelScript.h +│ │ ├── Animation/ # 动画系统 +│ │ │ ├── Animator.h +│ │ │ ├── AnimationClip.h +│ │ │ ├── AnimationCurve.h +│ │ │ ├── AnimationState.h +│ │ │ ├── AnimationBlendTree.h +│ │ │ ├── Skeleton.h +│ │ │ ├── Bone.h +│ │ │ ├── Skinning.h +│ │ │ └── BlendShape.h +│ │ ├── Particles/ # 粒子系统 +│ │ │ ├── ParticleSystem.h +│ │ │ ├── ParticleEmitter.h +│ │ │ ├── ParticleRenderer.h +│ │ │ ├── ParticleForce.h +│ │ │ ├── GPUParticles.h +│ │ │ └── VFXGraph.h +│ │ ├── Networking/ # 网络系统 +│ │ │ ├── NetworkManager.h +│ │ │ ├── NetworkClient.h +│ │ │ ├── NetworkServer.h +│ │ │ ├── NetworkPeer.h +│ │ │ ├── Packet.h +│ │ │ ├── Serializer.h +│ │ │ ├── RPC.h +│ │ │ ├── NetworkTransform.h +│ │ │ └── NetcodeProtocol.h +│ │ ├── UI/ # UI系统 +│ │ │ ├── Canvas.h +│ │ │ ├── Element.h +│ │ │ ├── Image.h +│ │ │ ├── Text.h +│ │ │ ├── Button.h +│ │ │ ├── ScrollView.h +│ │ │ ├── LayoutGroup.h +│ │ │ ├── UIRenderer.h +│ │ │ └── Font.h +│ │ ├── Navigation/ # 导航系统 +│ │ │ ├── NavMesh.h +│ │ │ ├── NavMeshAgent.h +│ │ │ ├── NavMeshQuery.h +│ │ │ ├── Obstacle.h +│ │ │ └── CrowdSystem.h +│ │ ├── Platforms/ # 平台层 +│ │ │ ├── Platform.h +│ │ │ ├── Windows.h +│ │ │ ├── Linux.h +│ │ │ ├── MacOS.h +│ │ │ ├── Android.h +│ │ │ ├── IOS.h +│ │ │ └── Web.h +│ │ └── XCGameEngine.h # 主头文件 +│ ├── src/ +│ │ ├── Core/ +│ │ ├── Math/ +│ │ ├── Components/ # 组件系统 +│ │ ├── Scene/ +│ │ ├── Renderer/ +│ │ ├── Resources/ +│ │ ├── Physics/ +│ │ ├── Audio/ +│ │ ├── Scripting/ +│ │ └── ... +│ └── third_party/ # 第三方库 +│ ├── stb/ +│ ├── json/ +│ ├── lua/ +│ ├── physx/ +│ └── etc. +│ +├── editor/ # 编辑器项目(你的UI) +│ ├── CMakeLists.txt +│ ├── src/ +│ │ ├── Application.h/cpp +│ │ ├── main.cpp +│ │ ├── Theme.h/cpp +│ │ ├── Core/ +│ │ │ ├── Event.h +│ │ │ ├── AssetItem.h +│ │ │ └── LogEntry.h +│ │ ├── Managers/ +│ │ │ ├── SelectionManager.h +│ │ │ ├── LogSystem.h/cpp +│ │ │ ├── ProjectManager.h/cpp +│ │ │ └── EditorSceneManager.h/cpp +│ │ ├── Panels/ +│ │ │ ├── Panel.h/cpp +│ │ │ ├── MenuBar.h/cpp +│ │ │ ├── HierarchyPanel.h/cpp +│ │ │ ├── InspectorPanel.h/cpp +│ │ │ ├── SceneViewPanel.h/cpp +│ │ │ ├── GameViewPanel.h/cpp +│ │ │ ├── ProjectPanel.h/cpp +│ │ │ ├── ConsolePanel.h/cpp +│ │ │ ├── AssetsBrowserPanel.h/cpp +│ │ │ ├── AnimationPanel.h/cpp +│ │ │ ├── ProfilerPanel.h/cpp +│ │ │ └── SettingsPanel.h/cpp +│ │ ├── Windows/ +│ │ │ ├── AssetImporter.h/cpp +│ │ │ ├── SceneHierarchyWindow.h/cpp +│ │ │ ├── ShaderEditor.h/cpp +│ │ │ ├── MaterialEditor.h/cpp +│ │ │ ├── AnimationEditor.h/cpp +│ │ │ └── PreferenceWindow.h/cpp +│ │ ├── Tools/ +│ │ │ ├── Gizmo.h/cpp +│ │ │ ├── SelectionTool.h/cpp +│ │ │ ├── MoveTool.h/cpp +│ │ │ ├── RotateTool.h/cpp +│ │ │ ├── ScaleTool.h/cpp +│ │ │ └── EditorCamera.h/cpp +│ │ ├── Editor/ +│ │ │ ├── EditorEngineLink.h/cpp +│ │ │ ├── EditorRenderView.h/cpp +│ │ │ ├── EditorModes.h +│ │ │ └── UndoRedo.h/cpp +│ │ └── ImGui/ +│ │ ├── ImGuiRenderer.h/cpp +│ │ ├── ImGuiTheme.h/cpp +│ │ └── ImGuiWidgets.h/cpp +│ └── assets/ +│ ├── fonts/ +│ ├── icons/ +│ └── themes/ +│ +├── runtime/ # 游戏运行时(独立可执行文件) +│ ├── CMakeLists.txt +│ ├── src/ +│ │ ├── GameMain.cpp +│ │ ├── RuntimeConfig.h +│ │ └── EntryPoint.cpp +│ └── resources/ +│ └── (烘焙后的场景和资源) +│ +├── tools/ # 工具链 +│ ├── AssetProcessor/ # 资源处理器 +│ ├── ShaderCompiler/ # 着色器编译器 +│ ├── SceneCooker/ # 场景烘焙工具 +│ ├── TextureConverter/ # 纹理转换工具 +│ ├── MeshOptimizer/ # 网格优化工具 +│ ├── AudioImporter/ # 音频导入工具 +│ ├── BuildTool/ # 构建打包工具 +│ └── ShaderDebugger/ # 着色器调试工具 +│ +├── content/ # 资源内容 +│ ├── Assets/ +│ │ ├── Scenes/ +│ │ ├── Materials/ +│ │ ├── Meshes/ +│ │ ├── Textures/ +│ │ ├── Audio/ +│ │ ├── Scripts/ +│ │ ├── Shaders/ +│ │ ├── Animations/ +│ │ ├── Prefabs/ +│ │ └── UI/ +│ ├── Packages/ # 包管理 +│ └── Library/ # 引擎库缓存 +│ ├── ShaderLibrary/ +│ ├── ShaderCache/ +│ ├── AssetDatabase/ +│ ├── SourceAssets/ +│ └── ImportCache/ +│ +└── docs/ # 文档 + ├── Architecture.md + ├── ComponentReference.md + ├── ShaderGuide.md + └── APIReference.md +``` + +--- + +## 第二章 核心层 (Core Layer) + +核心层提供引擎所有其他部分依赖的基础功能,是整个引擎的基石。 + +### 2.1 数学库 (Math Library) + +#### 2.1.1 设计目标 + +- **高性能**: SIMD 优化,支持 SSE/AVX/NEON +- **精确性**: 满足游戏精度需求,避免浮点误差 +- **完整性**: 覆盖游戏开发所需的所有数学类型 +- **可读性**: 简洁清晰的 API 设计 + +#### 2.1.2 核心类型 + +```cpp +namespace XCEngine { +namespace Math { + +// 向量类型 +struct Vector2 { float x, y; }; +struct Vector3 { float x, y, z; }; +struct Vector4 { float x, y, z, w; }; + +// 矩阵类型 +struct Matrix3x3; // 3D变换 +struct Matrix4x4; // 4D变换 +struct Matrix2x2; // 2D变换 + +// 四元数 - 避免欧拉角万向节锁 +struct Quaternion { + float x, y, z, w; + + // 旋转变换 + static Quaternion FromAxisAngle(const Vector3& axis, float radians); + static Quaternion FromEulerAngles(float pitch, float yaw, float roll); + static Quaternion FromRotationMatrix(const Matrix4x4& matrix); + static Quaternion Slerp(const Quaternion& a, const Quaternion& b, float t); + + Vector3 ToEulerAngles() const; + Matrix4x4 ToMatrix4x4() const; + Vector3 operator*(const Vector3& v) const; // 旋转向量 +}; + +// 变换 - 组合位置、旋转、缩放 +struct Transform { + Vector3 position = Vector3::Zero(); + Quaternion rotation = Quaternion::Identity(); + Vector3 scale = Vector3::One(); + + Matrix4x4 ToMatrix() const; + Transform Inverse() const; + Transform operator*(const Transform& other) const; // 组合变换 + Vector3 TransformPoint(const Vector3& point) const; + Vector3 TransformDirection(const Vector3& direction) const; +}; + +// 空间参照 +enum class Space { + Self, // 自身局部空间 + World // 世界空间 +}; + +// 颜色 +struct Color { float r, g, b, a; }; +struct LinearColor; // 线性空间颜色 +struct HDRColor; // HDR颜色 + +// 射线 - 用于射线检测和选择 +struct Ray { + Vector3 origin; + Vector3 direction; + + Vector3 GetPoint(float t) const; + bool Intersects(const Sphere& sphere, float& t) const; + bool Intersects(const Box& box, float& t) const; + bool Intersects(const Plane& plane, float& t) const; +}; + +// 包围体 +struct Sphere { Vector3 center; float radius; }; +struct Box { Vector3 center; Vector3 extents; Matrix4x4 transform; }; +struct Frustum; // 视锥体 +struct OBB; // 定向包围盒 +struct AABB; // 轴对齐包围盒 + +} // namespace Math +} // namespace XCEngine +``` + +#### 2.1.3 SIMD 优化示例 + +```cpp +// 使用 SIMD 进行向量运算 +struct alignas(16) Vector3_SIMD { + union { + __m128 simd; + struct { float x, y, z, w; }; + }; + + Vector3_SIMD operator+(const Vector3_SIMD& other) const { + Vector3_SIMD result; + result.simd = _mm_add_ps(simd, other.simd); + return result; + } + + float Dot(const Vector3_SIMD& other) const { + __m128 dot = _mm_mul_ps(simd, other.simd); + __m128 temp = _mm_movehl_ps(dot, dot); + dot = _mm_add_ss(dot, temp); + return _mm_cvtss_f32(dot); + } + + Vector3_SIMD Cross(const Vector3_SIMD& other) const { + Vector3_SIMD result; + __m128 a = _mm_shuffle_ps(simd, simd, _MM_SHUFFLE(3,0,2,1)); + __m128 b = _mm_shuffle_ps(other.simd, other.simd, _MM_SHUFFLE(3,1,0,2)); + result.simd = _mm_sub_ps(_mm_mul_ps(simd, a), _mm_mul_ps(other.simd, b)); + result.simd = _mm_shuffle_ps(result.simd, result.simd, _MM_SHUFFLE(3,0,2,1)); + return result; + } +}; +``` + +### 2.2 内存管理 (Memory Management) + +```cpp +namespace XCEngine { +namespace Memory { + +// 分配器基类 +class IAllocator { +public: + virtual ~IAllocator() = default; + + virtual void* Allocate(size_t size, size_t alignment = 0) = 0; + virtual void Free(void* ptr) = 0; + virtual void* Reallocate(void* ptr, size_t newSize) = 0; + + virtual size_t GetTotalAllocated() const = 0; + virtual size_t GetTotalFreed() const = 0; + virtual size_t GetPeakAllocated() const = 0; + virtual size_t GetAllocationCount() const = 0; + + virtual const char* GetName() const = 0; +}; + +// 线性分配器 - 快速分配和批量释放 +class LinearAllocator : public IAllocator { +public: + explicit LinearAllocator(size_t size, IAllocator* parent = nullptr); + ~LinearAllocator(); + + void* Allocate(size_t size, size_t alignment = 8) override; + void Free(void* ptr) override; // 只重置,不真正释放 + void Clear(); // 清空所有内存 + + void* GetMarker() const; + void SetMarker(void* marker); + +private: + byte* m_buffer = nullptr; + size_t m_capacity = 0; + size_t m_offset = 0; + IAllocator* m_parent = nullptr; +}; + +// 池分配器 - 高频小对象分配 +class PoolAllocator : public IAllocator { +public: + PoolAllocator(size_t blockSize, size_t poolSize, size_t alignment = 8); + ~PoolAllocator(); + + void* Allocate(size_t size, size_t alignment = 0) override; + void Free(void* ptr) override; + + bool Contains(void* ptr) const; + size_t GetBlockSize() const { return m_blockSize; } + size_t GetFreeBlockCount() const; + +private: + struct FreeNode { + FreeNode* next; + }; + + size_t m_blockSize = 0; + size_t m_alignment = 0; + void* m_memory = nullptr; + FreeNode* m_freeList = nullptr; + size_t m_totalBlocks = 0; + size_t m_freeBlocks = 0; +}; + +// 代理分配器 - 用于追踪和调试 +class ProxyAllocator : public IAllocator { +public: + ProxyAllocator(IAllocator* underlying, const char* name); + + void* Allocate(size_t size, size_t alignment = 0) override; + void Free(void* ptr) override; + void* Reallocate(void* ptr, size_t newSize) override; + + struct Stats { + size_t totalAllocated; + size_t totalFreed; + size_t peakAllocated; + size_t allocationCount; + size_t memoryOverhead; + }; + const Stats& GetStats() const; + +private: + IAllocator* m_underlying; + const char* m_name; + Stats m_stats; + Mutex m_mutex; +}; + +// 全局内存管理器 +class MemoryManager { +public: + static MemoryManager& Get(); + + void Initialize(); + void Shutdown(); + + IAllocator* GetSystemAllocator(); + IAllocator* GetPhysicsAllocator(); + IAllocator* GetRenderingAllocator(); + IAllocator* GetAudioAllocator(); + + std::unique_ptr CreateLinearAllocator(size_t size); + std::unique_ptr CreatePoolAllocator(size_t blockSize, size_t count); + std::unique_ptr CreateProxyAllocator(const char* name); + + void SetTrackAllocations(bool track); + void DumpMemoryLeaks(); + void GenerateMemoryReport(); +}; + +#define XE_ALLOC(allocator, size, ...) allocator->Allocate(size, ##__VA_ARGS__) +#define XE_FREE(allocator, ptr) allocator->Free(ptr) + +} +} +``` + +### 2.3 线程系统 (Threading) + +```cpp +namespace XCEngine { +namespace Threading { + +enum class TaskPriority : uint8_t { + Critical = 0, + High = 1, + Normal = 2, + Low = 3, + Idle = 4 +}; + +enum class TaskStatus : uint8_t { + Pending, + Scheduled, + Running, + Completed, + Failed, + Canceled +}; + +template +using Func = std::function; + +// 任务接口 +class ITask { +public: + virtual ~ITask() = default; + + virtual void Execute() = 0; + virtual void OnComplete() {} + virtual void OnCancel() {} + + TaskPriority GetPriority() const { return m_priority; } + TaskStatus GetStatus() const { return m_status; } + uint64 GetId() const { return m_id; } + +protected: + TaskPriority m_priority = TaskPriority::Normal; + TaskStatus m_status = TaskStatus::Pending; + uint64 m_id = 0; + std::atomic m_refCount{1}; +}; + +// Lambda 任务包装器 +template +class LambdaTask : public ITask { +public: + explicit LambdaTask(Func&& func, TaskPriority priority = TaskPriority::Normal) + : m_func(std::move(func)), m_priority(priority) {} + + void Execute() override { + m_func(); + } + +private: + Func m_func; +}; + +// 任务组 - 用于批量管理任务 +class TaskGroup { +public: + using Callback = std::function; + + TaskGroup(); + ~TaskGroup(); + + uint64 AddTask(std::unique_ptr task); + uint64 AddTask(Func&& func, TaskPriority priority = TaskPriority::Normal); + + void AddDependency(uint64 taskId, uint64 dependsOn); + void Wait(); + bool WaitFor(std::chrono::milliseconds timeout); + + void SetCompleteCallback(Callback&& callback); + bool IsComplete() const; + float GetProgress() const; +}; + +// 任务系统主类 +class TaskSystem { +public: + static TaskSystem& Get(); + + void Initialize(const TaskSystemConfig& config); + void Shutdown(); + + uint64 Submit(std::unique_ptr task); + uint64 Submit(Func&& func, TaskPriority priority = TaskPriority::Normal); + + TaskGroup* CreateTaskGroup(); + void DestroyTaskGroup(TaskGroup* group); + + void Wait(uint64 taskId); + uint32 GetWorkerThreadCount() const; + + void Update(); + + // 并行 For 循环 + template + void ParallelFor(int32 start, int32 end, Func&& func); + + void RunOnMainThread(Func&& func); +}; + +} +} +``` + +### 2.4 容器库 (Containers) + +```cpp +namespace XCEngine { +namespace Containers { + +// 动态数组 +template +class Array { +public: + using Iterator = T*; + using ConstIterator = const T*; + + Array() = default; + explicit Array(size_t capacity); + Array(size_t count, const T& value); + Array(std::initializer_list init); + ~Array(); + + Array(const Array& other); + Array(Array&& other) noexcept; + Array& operator=(const Array& other); + Array& operator=(Array&& other) noexcept; + + T& operator[](size_t index); + const T& operator[](size_t index) const; + + T* Data() { return m_data; } + const T* Data() const { return m_data; } + + size_t Size() const { return m_size; } + size_t Capacity() const { return m_capacity; } + + void Clear(); + void PushBack(const T& value); + void PushBack(T&& value); + template + T& EmplaceBack(Args&&... args); + void PopBack(); + +private: + T* m_data = nullptr; + size_t m_size = 0; + size_t m_capacity = 0; + IAllocator* m_allocator = nullptr; +}; + +// 字符串 +class String { +public: + String(); + String(const char* str); + String(const char* str, size_t len); + ~String(); + + String& operator+=(const String& other); + String& operator+=(const char* str); + + String Substring(size_t pos, size_t len = npos) const; + String Trim() const; + String ToLower() const; + String ToUpper() const; + + size_t Find(const char* str, size_t pos = 0) const; + bool StartsWith(const String& prefix) const; + bool EndsWith(const String& suffix) const; + + const char* CStr() const { return m_data; } + size_t Length() const { return m_length; } + +private: + char* m_data = nullptr; + size_t m_length = 0; + size_t m_capacity = 0; +}; + +// 哈希映射 +template +class HashMap { +public: + struct Pair { + Key first; + Value second; + }; + + HashMap() = default; + explicit HashMap(size_t bucketCount, IAllocator* allocator = nullptr); + + Value& operator[](const Key& key); + Value* Find(const Key& key); + const Value* Find(const Key& key) const; + bool Contains(const Key& key) const; + + bool Insert(const Key& key, const Value& value); + bool Erase(const Key& key); + void Clear(); + + size_t Size() const { return m_size; } + +private: + size_t GetBucketIndex(const Key& key) const; + void Resize(); + + struct Bucket { + Array pairs; + }; + Array m_buckets; + size_t m_bucketCount = 0; + size_t m_size = 0; + float m_loadFactor = 0.75f; + IAllocator* m_allocator = nullptr; +}; + +} // namespace Containers +} // namespace XCEngine +``` + +### 2.5 日志与调试系统 + +```cpp +namespace XCEngine { +namespace Core { + +// 事件系统 - 基础事件系统(线程安全版本) +template +class Event { +public: + using Callback = std::function; + using Listener = std::pair; + using Iterator = typename std::vector::iterator; + + uint64_t Subscribe(Callback callback) { + std::lock_guard lock(m_mutex); + uint64_t id = ++m_nextId; + m_listeners.emplace_back(id, std::move(callback)); + return id; + } + + void Unsubscribe(uint64_t id) { + std::lock_guard lock(m_mutex); + m_pendingUnsubscribes.push_back(id); + } + + void ProcessUnsubscribes() { + std::lock_guard lock(m_mutex); + for (uint64_t id : m_pendingUnsubscribes) { + m_listeners.erase( + std::remove_if(m_listeners.begin(), m_listeners.end(), + [id](const auto& pair) { return pair.first == id; }), + m_listeners.end() + ); + } + m_pendingUnsubscribes.clear(); + } + + void Invoke(Args... args) const { + // 注意:这里不加锁以避免回调中调用Unsubscribe导致的死锁 + // 实际使用时应在调用前确保没有并发的Unsubscribe + // 或者使用副本进行调用 + + if (!m_pendingUnsubscribes.empty()) { + std::vector listenersCopy; + { + std::lock_guard lock(m_mutex); + listenersCopy = m_listeners; + m_pendingUnsubscribes.clear(); + } + for (const auto& [id, callback] : listenersCopy) { + callback(args...); + } + } else { + for (const auto& [id, callback] : m_listeners) { + callback(args...); + } + } + } + + void Clear() { + std::lock_guard lock(m_mutex); + m_listeners.clear(); + } + + Iterator begin() { return m_listeners.begin(); } + Iterator end() { return m_listeners.end(); } + +private: + mutable std::mutex m_mutex; + std::vector m_listeners; + std::vector m_pendingUnsubscribes; + uint64_t m_nextId = 0; +}; + +// 基础类型定义 +// 注意:String 定义在 Containers 命名空间中,避免与 Core::String 冲突 +using int8 = int8_t; +using int16 = int16_t; +using int32 = int32_t; +using int64 = int64_t; +using uint8 = uint8_t; +using uint16 = uint16_t; +using uint32 = uint32_t; +using uint64 = uint64_t; +using byte = uint8_t; + +// 引用计数基类 +class RefCounted { +public: + RefCounted() : m_refCount(1) {} + virtual ~RefCounted() = default; + + void AddRef() { ++m_refCount; } + void Release() { + if (--m_refCount == 0) { + delete this; + } + } + + uint32_t GetRefCount() const { return m_refCount.load(); } + +protected: + std::atomic m_refCount; +}; + +// 智能指针别名 +template +using Ref = std::shared_ptr; + +template +using UniqueRef = std::unique_ptr; + +} // namespace Core +} + +namespace XCEngine { +namespace Debug { + +enum class LogLevel : uint8_t { + Verbose = 0, + Debug = 1, + Info = 2, + Warning = 3, + Error = 4, + Fatal = 5 +}; + +enum class LogCategory { + General, + Rendering, + Physics, + Audio, + Scripting, + Network, + Memory, + Threading, + FileSystem, + Custom +}; + +struct LogEntry { + LogLevel level; + LogCategory category; + String message; + String file; + int32 line; + String function; + uint64 timestamp; + uint32 threadId; +}; + +class ILogSink { +public: + virtual ~ILogSink() = default; + virtual void Log(const LogEntry& entry) = 0; + virtual void Flush() = 0; +}; + +class ConsoleLogSink : public ILogSink { +public: + void Log(const LogEntry& entry) override; + void Flush() override; + void SetColorOutput(bool enable); + void SetMinimumLevel(LogLevel level); +}; + +class FileLogSink : public ILogSink { +public: + explicit FileLogSink(const String& filePath); + ~FileLogSink(); + void Log(const LogEntry& entry) override; + void Flush() override; +private: + String m_filePath; + FileWriter m_writer; +}; + +class Logger { +public: + static Logger& Get(); + + void Initialize(); + void Shutdown(); + + void AddSink(std::unique_ptr sink); + void RemoveSink(ILogSink* sink); + + void Log(LogLevel level, LogCategory category, + const String& message, const char* file = nullptr, + int32 line = 0, const char* function = nullptr); + + void Verbose(LogCategory category, const String& message); + void Debug(LogCategory category, const String& message); + void Info(LogCategory category, const String& message); + void Warning(LogCategory category, const String& message); + void Error(LogCategory category, const String& message); + void Fatal(LogCategory category, const String& message); + + void SetMinimumLevel(LogLevel level); + void SetCategoryEnabled(LogCategory category, bool enabled); +}; + +#define XE_LOG(category, level, message) \ + XCEngine::Debug::Logger::Get().Log(level, category, message, __FILE__, __LINE__, __FUNCTION__) + +#define XE_ASSERT(condition, message) \ + if (!(condition)) { \ + XCEngine::Debug::Logger::Get().Fatal(XCEngine::Debug::LogCategory::General, message); \ + __debugbreak(); \ + } + +// 性能分析器 +class Profiler { +public: + static Profiler& Get(); + + void Initialize(); + void Shutdown(); + + void BeginProfile(const char* name); + void EndProfile(); + + void BeginFrame(); + void EndFrame(); + + void MarkEvent(const char* name, uint64_t timestamp, uint32_t threadId); + void SetMarker(const char* name, uint32_t color); + + void ExportChromeTracing(const String& filePath); +}; + +#define XE_PROFILE_BEGIN(name) XCEngine::Debug::Profiler::Get().BeginProfile(name) +#define XE_PROFILE_END() XCEngine::Debug::Profiler::Get().EndProfile() +#define XE_PROFILE_FUNCTION() XE_PROFILE_BEGIN(__FUNCTION__) + +} +} +``` + +--- + +## 第三章 组件系统 (GameObject + Component) + +> 本架构参考**传统Unity的GameObject + Component模式**。 +> - GameObject是实体容器,包含Transform等内置组件 +> - Component是挂载在GameObject上的class(引用类型),包含数据和行为 +> - Component有完整的生命周期(Awake, Start, Update, OnDestroy等) +> - Scene直接管理GameObject列表,没有World中间层 + +### 3.1 组件系统架构 + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ GameObject + Component Architecture │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌───────────────────────────────────────────────────────────────────────┐ │ +│ │ Scene (场景) │ │ +│ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ +│ │ │ Scene │ │ +│ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ +│ │ │ │ GameObject List │ │ │ +│ │ │ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │ │ +│ │ │ │ │ GameObject │ │ GameObject │ │ GameObject │ │ │ │ +│ │ │ │ │ - name │ │ - name │ │ - name │ │ │ │ +│ │ │ │ │ - transform│ │ - transform│ │ - transform│ │ │ │ +│ │ │ │ │ - components│ │ - components│ │ - components│ │ │ │ +│ │ │ │ │ └ Renderer│ │ └ Camera │ │ └ Script │ │ │ │ +│ │ │ │ └────────────┘ └────────────┘ └────────────┘ │ │ │ +│ │ │ └─────────────────────────────────────────────────────────┘ │ │ +│ └───────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 3.2 游戏对象 (GameObject) + +```cpp +namespace XCEngine { + +class Scene; +class Transform; +class Component; + +// GameObject: 游戏对象(类Unity GameObject) +// 传统Unity风格的GameObject,包含内置组件和用户组件 +// 生命周期由 Scene 的 unique_ptr 管理,不需要引用计数 +class GameObject { +public: + GameObject(); + ~GameObject(); + + // 内部构造 - 用于Scene创建GameObject时设置初始属性 + struct ConstructParams { + String name = "GameObject"; + GameObject* parent = nullptr; + bool active = true; + }; + + // 工厂方法(替代公有构造函数) + static GameObject* Create(const ConstructParams& params = {}); + static void Destroy(GameObject* obj); + + String name; // 对象名称 + bool active = true; // 激活状态 + + TransformComponent& GetTransform() { return m_transform; } + const TransformComponent& GetTransform() const { return m_transform; } + + Scene* GetScene() const { return m_scene; } + + // 组件管理 + template + T* AddComponent(); + + template + void RemoveComponent(); + + template + T* GetComponent() const; + + template + std::vector GetComponents() const; + + template + T* GetComponentInChildren() const; + + template + std::vector GetComponentsInChildren() const; + + template + T* GetComponentInParent() const; + + // 层级管理 + GameObject* GetParent() const; + void SetParent(GameObject* parent); + void SetParent(GameObject* parent, bool worldPositionStays); + const std::vector& GetChildren() const; + GameObject* GetChild(int index) const; + int GetChildCount() const; + int GetSiblingIndex() const; + void SetSiblingIndex(int index); + + // 激活状态 + void SetActive(bool active); + bool IsActive() const; + bool IsActiveInHierarchy() const; + + // 场景查找(静态方法,内部使用SceneManager::GetActiveScene) + static GameObject* Find(const String& name); + static std::vector FindObjectsOfType(); + static std::vector FindGameObjectsWithTag(const String& tag); + + // 生命周期 + void Destroy(); + +private: + void AddComponentInternal(Component* component); + void RemoveComponentInternal(Component* component); + + std::vector> m_components; + + // 组件类型索引 - 用于O(1)查询(类型ID -> 组件索引) + // 每个 AddComponent/RemoveComponent 时更新 + std::unordered_map m_componentTypeIndex; + + std::vector m_children; + GameObject* m_parent = nullptr; + Scene* m_scene = nullptr; + + // TransformComponent是GameObject的内置组件 + // 注意:TransformComponent继承自Component,需要在构造后设置m_gameObject + TransformComponent m_transform; + + void Initialize(const ConstructParams& params); + + friend class Scene; + friend class TransformComponent; +}; + +// GameObject实现 +inline GameObject::GameObject() { + // m_transform需要在构造后初始化m_gameObject +} + +inline GameObject::~GameObject() { + // 销毁所有子对象 + for (auto* child : m_children) { + delete child; + } +} + +inline GameObject* GameObject::Create(const ConstructParams& params) { + GameObject* obj = new GameObject(); + obj->Initialize(params); + return obj; +} + +inline void GameObject::Destroy(GameObject* obj) { + delete obj; +} + +inline void GameObject::Initialize(const ConstructParams& params) { + name = params.name; + active = params.active; + + // 设置TransformComponent的m_gameObject指针 + m_transform.m_gameObject = this; + + // 设置父子关系 + if (params.parent) { + params.parent->m_children.push_back(this); + m_parent = params.parent; + } +} + +inline void GameObject::Destroy() { + if (m_scene) { + m_scene->DestroyGameObject(this); + } else { + delete this; + } +} + +// 静态方法实现 +inline GameObject* GameObject::Find(const String& name) { + return SceneManager::Get().GetActiveScene()->Find(name); +} + +inline std::vector GameObject::FindObjectsOfType() { + return SceneManager::Get().GetActiveScene()->FindObjectsOfType(); +} + +inline std::vector GameObject::FindGameObjectsWithTag(const String& tag) { + return SceneManager::Get().GetActiveScene()->FindGameObjectsWithTag(tag); +} + +// GameObject创建辅助类 +class GameObjectBuilder { +public: + explicit GameObjectBuilder(const String& name = "GameObject"); + ~GameObjectBuilder() = default; + + template + GameObjectBuilder& AddComponent(Args&&... args); + + GameObject* Build(); + +private: + String m_name; + std::vector> m_components; +}; + +} +``` + +### 3.3 组件 (Component) + +```cpp +namespace XCEngine { + +class GameObject; + +// 组件基类(类Unity MonoBehaviour) +// 包含完整的生命周期方法,用户组件继承此类 +// 注意:组件由GameObject拥有和管理生命周期,不需要引用计数 +class Component { +public: + Component(); + virtual ~Component(); + + // 所属GameObject + GameObject* gameObject() const { return m_gameObject; } + TransformComponent& transform() const { return m_gameObject->GetTransform(); } + + // 激活状态 + bool IsEnabled() const { return m_enabled; } + void SetEnabled(bool enabled) { m_enabled = enabled; } + + // 场景引用 + Scene* GetScene() const; + + // 组件查找 + template + T* GetComponent() const { return m_gameObject->GetComponent(); } + + template + std::vector GetComponents() const { return m_gameObject->GetComponents(); } + + // ======================================== + // 生命周期(类Unity MonoBehaviour) + // ======================================== + + // 创建时调用(即使组件被禁用也会调用) + virtual void Awake() {} + + // 首次启用时调用(当对象和组件都被启用时) + virtual void Start() {} + + // 每帧调用(当组件启用时) + virtual void Update(float deltaTime) {} + + // 物理更新(固定时间间隔) + virtual void FixedUpdate() {} + + // 在Update之后每帧调用 + virtual void LateUpdate(float deltaTime) {} + + // 销毁时调用 + virtual void OnDestroy() {} + + // 当组件被启用时调用 + virtual void OnEnable() {} + + // 当组件被禁用时调用 + virtual void OnDisable() {} + + // ======================================== + // 物理回调(类Unity) + // ======================================== + + virtual void OnCollisionEnter(const Collision& collision) {} + virtual void OnCollisionStay(const Collision& collision) {} + virtual void OnCollisionExit(const Collision& collision) {} + + virtual void OnTriggerEnter(Collider* other) {} + virtual void OnTriggerStay(Collider* other) {} + virtual void OnTriggerExit(Collider* other) {} + + virtual void OnMouseDown() {} + virtual void OnMouseDrag() {} + virtual void OnMouseEnter() {} + virtual void OnMouseExit() {} + virtual void OnMouseOver() {} + virtual void OnMouseUp() {} + virtual void OnMouseUpAsButton() {} + + virtual void OnTriggerEnter2D(Collider2D* other) {} + virtual void OnTriggerExit2D(Collider2D* other) {} + virtual void OnCollisionEnter2D(Collision2D* collision) {} + virtual void OnCollisionExit2D(Collision2D* collision) {} + + // ======================================== + // 消息发送 + // ======================================== + + // 发送消息到同GameObject上的其他组件 + void SendMessage(const String& methodName, const void* value = nullptr); + void SendMessageUpwards(const String& methodName, const void* value = nullptr); + void BroadcastMessage(const String& methodName, const void* value = nullptr); + +protected: + GameObject* m_gameObject = nullptr; + bool m_enabled = true; + + friend class GameObject; +}; + +// 组件类型注册(用于运行时类型识别) +class ComponentTypeRegistry { +public: + static ComponentTypeRegistry& Get(); + + template + static uint32_t GetTypeId() { + static uint32_t id = Get().Register(typeid(T).name(), static_cast(-1)); + return id; + } + + template + static uint32_t GetTypeId(const char* typeName) { + static uint32_t id = Get().Register(typeName, static_cast(-1)); + return id; + } + + static uint32_t GetTypeIdFromName(const char* typeName) { + return Get().GetIdByName(typeName); + } + + static const char* GetTypeName(uint32_t typeId) { + return Get().GetNameById(typeId); + } + +private: + uint32_t Register(const char* typeName, uint32_t suggestedId); + uint32_t GetIdByName(const char* typeName) const; + const char* GetNameById(uint32_t typeId) const; + + std::atomic m_nextTypeId{0}; + std::unordered_map m_idToName; + std::unordered_map m_nameToId; + Mutex m_mutex; +}; + +// ============================================================================ +// ============================================================================ +// TransformComponent - GameObject的内置组件(类Unity Transform) +// 继承自 Component,包含父子层级关系 +// ============================================================================ + +class TransformComponent : public Component { +public: + // 局部变换 + Vector3 GetLocalPosition() const { return m_localPosition; } + void SetLocalPosition(const Vector3& position) { m_localPosition = position; SetDirty(); } + + Quaternion GetLocalRotation() const { return m_localRotation; } + void SetLocalRotation(const Quaternion& rotation) { m_localRotation = rotation; SetDirty(); } + + Vector3 GetLocalScale() const { return m_localScale; } + void SetLocalScale(const Vector3& scale) { m_localScale = scale; SetDirty(); } + + // 世界变换(通过计算得出) + Vector3 GetPosition() const; + void SetPosition(const Vector3& position); + + Quaternion GetRotation() const; + void SetRotation(const Quaternion& rotation); + + Vector3 GetScale() const; + void SetScale(const Vector3& scale); + + // 方向向量 + Vector3 GetForward() const { return GetRotation() * Vector3::Forward(); } + Vector3 GetRight() const { return GetRotation() * Vector3::Right(); } + Vector3 GetUp() const { return GetRotation() * Vector3::Up(); } + + // 矩阵 + const Matrix4x4& GetLocalToWorldMatrix() const; + Matrix4x4 GetWorldToLocalMatrix() const; + + // 层级操作 + TransformComponent* GetParent() const { return m_parent; } + void SetParent(TransformComponent* parent, bool worldPositionStays = true); + + int GetChildCount() const { return static_cast(m_children.size()); } + TransformComponent* GetChild(int index) const; + TransformComponent* Find(const String& name) const; + + void DetachChildren(); + void SetAsFirstSibling(); + void SetAsLastSibling(); + void SetSiblingIndex(int index); + int GetSiblingIndex() const; + + // 变换操作 + void LookAt(const Vector3& target); + void LookAt(const Vector3& target, const Vector3& up); + void Rotate(const Vector3& eulers); + void Rotate(const Vector3& axis, float angle); + void Translate(const Vector3& translation); + void Translate(const Vector3& translation, Math::Space relativeTo); + + // 点变换 + Vector3 TransformPoint(const Vector3& point) const; + Vector3 InverseTransformPoint(const Vector3& point) const; + Vector3 TransformDirection(const Vector3& direction) const; + Vector3 InverseTransformDirection(const Vector3& direction) const; + + // 设为脏(需要重新计算世界变换) + void SetDirty() { m_dirty = true; } + +private: + Vector3 m_localPosition = Vector3::Zero(); + Quaternion m_localRotation = Quaternion::Identity(); + Vector3 m_localScale = Vector3::One(); + + TransformComponent* m_parent = nullptr; + std::vector m_children; + + mutable Matrix4x4 m_localToWorldMatrix; + mutable Matrix4x4 m_worldToLocalMatrix; + mutable Vector3 m_worldPosition; + mutable Quaternion m_worldRotation; + mutable Vector3 m_worldScale; + mutable bool m_dirty = true; + + void UpdateWorldTransform() const; + + friend class GameObject; +}; + +// 渲染组件(继承Component) +class RenderMeshComponent : public Component { +public: + void Awake() override; + void Start() override; + void Update(float deltaTime) override; + + ResourceGUID GetMesh() const { return m_meshGuid; } + void SetMesh(const ResourceGUID& guid); + + ResourceGUID GetMaterial() const { return m_materialGuid; } + void SetMaterial(const ResourceGUID& guid); + + bool GetCastShadows() const { return m_castShadows; } + void SetCastShadows(bool cast) { m_castShadows = cast; } + + bool GetReceiveShadows() const { return m_receiveShadows; } + void SetReceiveShadows(bool receive) { m_receiveShadows = receive; } + +private: + ResourceGUID m_meshGuid; + ResourceGUID m_materialGuid; + bool m_castShadows = true; + bool m_receiveShadows = true; +}; + +// 光源组件 - 继承Component(类Unity Light) +class RenderLightComponent : public Component { +public: + void Awake() override; + void Update(float deltaTime) override; + + enum class LightType : uint8_t { + Directional, + Point, + Spot, + Area + }; + + void SetLightType(LightType type) { m_type = type; } + LightType GetLightType() const { return m_type; } + + void SetColor(const Vector3& color) { m_color = color; } + Vector3 GetColor() const { return m_color; } + + void SetIntensity(float intensity) { m_intensity = intensity; } + float GetIntensity() const { return m_intensity; } + + void SetRange(float range) { m_range = range; } + float GetRange() const { return m_range; } + + void SetSpotAngle(float angle) { m_spotAngle = angle; } + float GetSpotAngle() const { return m_spotAngle; } + + void SetCastShadows(bool cast) { m_castShadows = cast; } + bool GetCastShadows() const { return m_castShadows; } + + void SetShadowResolution(uint32_t resolution) { m_shadowResolution = resolution; } + uint32_t GetShadowResolution() const { return m_shadowResolution; } + + void SetCullingMask(int32_t mask) { m_cullingMask = mask; } + int32_t GetCullingMask() const { return m_cullingMask; } + +private: + LightType m_type = LightType::Point; + Vector3 m_color = Vector3::One(); + float m_intensity = 1.0f; + float m_range = 10.0f; + float m_spotAngle = 30.0f; + float m_penumbraAngle = 5.0f; + bool m_castShadows = true; + uint32_t m_shadowResolution = 1024; + float m_shadowBias = 0.005f; + float m_normalOffsetBias = 0.001f; + float m_nearPlane = 0.1f; + int32_t m_cullingMask = -1; + float m_intensityVariation = 0.0f; + ResourceGUID m_cookieTextureGuid = ResourceGUID::Invalid; + float m_cookieSize = 5.0f; +}; + +// 相机组件 - 继承Component(类Unity Camera) +class CameraComponent : public Component { +public: + void Awake() override; + void Start() override; + void Update(float deltaTime) override; + + enum class ProjectionType : uint8_t { + Perspective, + Orthographic + }; + + void SetProjectionType(ProjectionType type) { m_projectionType = type; } + ProjectionType GetProjectionType() const { return m_projectionType; } + + void SetFieldOfView(float fov) { m_fieldOfView = fov; } + float GetFieldOfView() const { return m_fieldOfView; } + + void SetOrthographicSize(float size) { m_orthographicSize = size; } + float GetOrthographicSize() const { return m_orthographicSize; } + + void SetNearClipPlane(float near) { m_nearPlane = near; } + float GetNearClipPlane() const { return m_nearPlane; } + + void SetFarClipPlane(float far) { m_farPlane = far; } + float GetFarClipPlane() const { return m_farPlane; } + + void SetViewport(const Rect& rect) { m_viewportRect = rect; } + const Rect& GetViewport() const { return m_viewportRect; } + + void SetCullingMask(int32_t mask) { m_cullingMask = mask; } + int32_t GetCullingMask() const { return m_cullingMask; } + + void SetDepth(float depth) { m_depth = depth; } + float GetDepth() const { return m_depth; } + + Matrix4x4 GetViewMatrix() const; + Matrix4x4 GetProjectionMatrix() const; + Matrix4x4 GetViewProjectionMatrix() const; + + Vector3 ScreenToWorldPoint(const Vector3& screenPoint) const; + Vector3 WorldToScreenPoint(const Vector3& worldPoint) const; + Ray ScreenPointToRay(const Vector2& screenPoint) const; + + Frustum& GetFrustum() { return m_frustum; } + +private: + ProjectionType m_projectionType = ProjectionType::Perspective; + float m_fieldOfView = 60.0f; + float m_orthographicSize = 5.0f; + float m_nearPlane = 0.1f; + float m_farPlane = 1000.0f; + float m_aspectRatio = 16.0f / 9.0f; + Rect m_viewportRect = Rect(0, 0, 1, 1); + float m_depth = 0.0f; + int32_t m_cullingMask = -1; + Frustum m_frustum; +}; + +// 物理组件 - 继承Component(类Unity Rigidbody) +class RigidBodyComponent : public Component { +public: + void Awake() override; + void Start() override; + void FixedUpdate() override; + void OnEnable() override; + void OnDisable() override; + void OnDestroy() override; + + // 物理回调(类Unity) + void OnCollisionEnter(const Collision& collision) override; + void OnCollisionStay(const Collision& collision) override; + void OnCollisionExit(const Collision& collision) override; + void OnTriggerEnter(Collider* other) override; + void OnTriggerStay(Collider* other) override; + void OnTriggerExit(Collider* other) override; + + enum class BodyType : uint8_t { + Dynamic, + Kinematic, + Static + }; + + void SetBodyType(BodyType type) { m_bodyType = type; } + BodyType GetBodyType() const { return m_bodyType; } + + void SetMass(float mass) { m_mass = mass; } + float GetMass() const { return m_mass; } + + void SetLinearDamping(float damping) { m_linearDamping = damping; } + float GetLinearDamping() const { return m_linearDamping; } + + void SetAngularDamping(float damping) { m_angularDamping = damping; } + float GetAngularDamping() const { return m_angularDamping; } + + void AddForce(const Vector3& force, ForceMode mode = ForceMode::Force); + void AddForceAtPosition(const Vector3& force, const Vector3& position, ForceMode mode = ForceMode::Force); + void AddTorque(const Vector3& torque, ForceMode mode = ForceMode::Force); + + void SetVelocity(const Vector3& velocity); + Vector3 GetVelocity() const; + + void SetAngularVelocity(const Vector3& velocity); + Vector3 GetAngularVelocity() const; + + void SetUseGravity(bool use) { m_useGravity = use; } + bool IsUsingGravity() const { return m_useGravity; } + + void SetIsKinematic(bool kinematic); + bool IsKinematic() const; + + enum class InterpolateMode : uint8_t { + None, + Interpolate, + Extrapolate + }; + + void SetInterpolate(InterpolateMode mode); + InterpolateMode GetInterpolate() const { return m_interpolateMode; } + + // 获取物理引擎内部句柄(用于 PhysicsWorld 调用,避免 GameObject* 悬空指针) + void* GetPhysicsHandle() const { return m_physicsHandle; } + void SetPhysicsHandle(void* handle) { m_physicsHandle = handle; } + +private: + BodyType m_bodyType = BodyType::Dynamic; + float m_mass = 1.0f; + float m_linearDamping = 0.0f; + float m_angularDamping = 0.05f; + Vector3 m_velocity; + Vector3 m_angularVelocity; + bool m_useGravity = true; + InterpolateMode m_interpolateMode = InterpolateMode::None; + + // 物理引擎内部句柄(由 PhysicsWorld 设置) + void* m_physicsHandle = nullptr; +}; + +// 碰撞组件 - 继承Component(类Unity Collider) +class ColliderComponent : public Component { +public: + void Awake() override; + void Start() override; + + enum class ShapeType : uint8_t { + Box, + Sphere, + Capsule, + Mesh, + ConvexHull + }; + + void SetShapeType(ShapeType type) { m_shapeType = type; } + ShapeType GetShapeType() const { return m_shapeType; } + + void SetCenter(const Vector3& center) { m_center = center; } + Vector3 GetCenter() const { return m_center; } + + void SetSize(const Vector3& size) { m_boxSize = size; } + Vector3 GetSize() const { return m_boxSize; } + + void SetRadius(float radius) { m_sphereRadius = radius; } + float GetRadius() const { return m_sphereRadius; } + + void SetIsTrigger(bool trigger) { m_isTrigger = trigger; } + bool IsTrigger() const { return m_isTrigger; } + + void SetMaterial(const ResourceGUID& guid); + ResourceGUID GetMaterial() const { return m_materialGuid; } + +private: + ShapeType m_shapeType = ShapeType::Box; + Vector3 m_boxSize = Vector3::One(); + float m_sphereRadius = 0.5f; + float m_capsuleRadius = 0.5f; + float m_capsuleHeight = 2.0f; + + Vector3 m_center = Vector3::Zero(); + Quaternion m_rotation = Quaternion::Identity(); + + int32_t m_layer = 0; + int32_t m_mask = -1; + + float m_friction = 0.5f; + float m_restitution = 0.0f; + + bool m_isTrigger = false; + bool m_convex = true; + + ResourceGUID m_materialGuid = ResourceGUID::Invalid; + ResourceGUID m_meshGuid = ResourceGUID::Invalid; + + // 物理引擎内部句柄(由 PhysicsWorld 设置) + void* m_physicsHandle = nullptr; +}; + +// 关节组件 - 继承Component(类Unity Joint) +class JointComponent : public Component { +public: + void Awake() override; + void OnDestroy() override; + + enum class Type : uint8_t { + Hinge, // 铰链关节 + Slider, // 滑块关节 + Spring, // 弹簧关节 + Fixed, // 固定关节 + Configurable, // 可配置关节 + Character // 角色关节 + }; + + enum class Axis { + X, Y, Z + }; + + void SetJointType(Type type) { m_jointType = type; } + Type GetJointType() const { return m_jointType; } + + void SetConnectedBody(GameObject* body) { m_connectedBody = body; } + GameObject* GetConnectedBody() const { return m_connectedBody; } + + void SetAnchor(const Vector3& anchor) { m_anchor = anchor; } + Vector3 GetAnchor() const { return m_anchor; } + + void SetAxis(const Vector3& axis) { m_axis = axis; } + Vector3 GetAxis() const { return m_axis; } + + void SetBreakForce(float force) { m_breakForce = force; } + float GetBreakForce() const { return m_breakForce; } + + void SetBreakTorque(float torque) { m_breakTorque = torque; } + float GetBreakTorque() const { return m_breakTorque; } + + void SetEnableCollision(bool enable) { m_enableCollision = enable; } + bool GetEnableCollision() const { return m_enableCollision; } + + bool IsBroken() const { return m_broken; } + +private: + Type m_jointType = Type::Fixed; + GameObject* m_connectedBody = nullptr; + + Vector3 m_anchor = Vector3::Zero(); + Vector3 m_axis = Vector3::Up(); + Vector3 m_secondaryAxis = Vector3::Right(); + + float m_breakForce = INFINITY; + float m_breakTorque = INFINITY; + bool m_enableCollision = false; + bool m_broken = false; + + void* m_physicsJoint = nullptr; +}; + +// 音频源组件(继承Component) +class AudioSourceComponent : public Component { +public: + void Awake() override; + void Start() override; + void Update(float deltaTime) override; + void OnEnable() override; + void OnDisable() override; + void OnDestroy() override; + + void Play(); + void Stop(); + void Pause(); + + bool IsPlaying() const; + bool IsPaused() const; + + void SetClip(const ResourceGUID& guid); + ResourceGUID GetClip() const { return m_clipGuid; } + + void SetLoop(bool loop) { m_loop = loop; } + bool GetLoop() const { return m_loop; } + + void SetVolume(float volume) { m_volume = volume; } + float GetVolume() const { return m_volume; } + + void SetPitch(float pitch) { m_pitch = pitch; } + float GetPitch() const { return m_pitch; } + + void SetSpatialBlend(float blend) { m_spatialBlend = blend; } + float GetSpatialBlend() const { return m_spatialBlend; } + +private: + ResourceGUID m_clipGuid; + bool m_playOnAwake = false; + bool m_loop = false; + bool m_isPlaying = false; + bool m_isPaused = false; + float m_volume = 1.0f; + float m_pitch = 1.0f; + float m_spatialBlend = 1.0f; + float m_minDistance = 1.0f; + float m_maxDistance = 500.0f; +}; + +// 音频监听器组件(继承Component) +class AudioListenerComponent : public Component { +public: + void Awake() override; + + void SetDopplerFactor(float factor) { m_dopplerFactor = factor; } + float GetDopplerFactor() const { return m_dopplerFactor; } + + void SetMasterVolume(float volume) { m_masterVolume = volume; } + float GetMasterVolume() const { return m_masterVolume; } + +private: + float m_dopplerFactor = 1.0f; + float m_masterVolume = 1.0f; +}; + +} // namespace XCEngine +``` + +### 3.5 场景 (Scene) + +> 说明:传统Unity的Scene直接管理GameObject列表,没有World中间层。 + +```cpp +namespace XCEngine { + +// 场景(类Unity Scene) +// 直接管理GameObject列表,不需要World +class Scene { +public: + Scene(); + ~Scene(); + + // 场景名称 + const String& GetName() const { return m_name; } + void SetName(const String& name) { m_name = name; } + + // GameObject管理(类Unity Scene API) + GameObject* CreateGameObject(const String& name = "GameObject") { + GameObject::ConstructParams params; + params.name = name; + params.parent = nullptr; + params.active = true; + + GameObject* obj = GameObject::Create(params); + obj->m_scene = this; + AddGameObject(obj); + return obj; + } + + GameObject* CreateGameObject(const String& name, GameObject* parent) { + GameObject::ConstructParams params; + params.name = name; + params.parent = parent; + params.active = true; + + GameObject* obj = GameObject::Create(params); + obj->m_scene = this; + AddGameObject(obj); + return obj; + } + + void DestroyGameObject(GameObject* obj); + + // 根GameObject(没有父对象的顶层GameObject,从所有GameObject中筛选) + // 注意:此方法为O(n)复杂度,与Unity的Scene.GetRootGameObjects行为一致 + // Unity也不缓存根对象,因为GameObject层级变化频繁,缓存维护成本可能更高 + std::vector GetRootGameObjects() const { + std::vector roots; + roots.reserve(m_gameObjects.size() / 2); // 预分配合理容量 + for (auto& obj : m_gameObjects) { + if (obj->GetParent() == nullptr) { + roots.push_back(obj.get()); + } + } + return roots; + } + + // 查找 + GameObject* Find(const String& name) const; + GameObject* FindGameObjectWithTag(const String& tag) const; + std::vector FindGameObjectsWithTag(const String& tag) const; + template + std::vector FindObjectsOfType() const; + T* FindObjectOfType() const; + + // 激活状态 + bool IsActive() const { return m_isActive; } + void SetActive(bool active); + + // 生命周期 + void Load(const String& filePath); + void LoadAsync(const String& filePath, std::function callback); + void Save(const String& filePath); + + // 更新(内部调用) + void Update(float deltaTime); + void FixedUpdate(float fixedDeltaTime); + void LateUpdate(float deltaTime); + + // 调试 + void DebugDraw(); + int GetObjectCount() const { return m_gameObjects.size(); } + +private: + void AddGameObject(GameObject* obj); + void RemoveGameObject(GameObject* obj); + + String m_name; + std::vector> m_gameObjects; + bool m_isActive = true; + + friend class GameObject; + friend class SceneManager; +}; + +// 场景管理器 +class SceneManager { +public: + static SceneManager& Get(); + + void Initialize(); + void Shutdown(); + + // 场景操作 + Scene* CreateScene(const String& name); + void LoadScene(const String& filePath); + void LoadSceneAsync(const String& filePath, std::function callback); + void UnloadScene(Scene* scene); + void UnloadScene(const String& sceneName); + + // 活动场景 + void SetActiveScene(Scene* scene); + void SetActiveScene(const String& sceneName); + Scene* GetActiveScene() const; + + // 查找 + Scene* GetScene(const String& name) const; + std::vector GetAllScenes() const; + + // 更新 + void Update(float deltaTime); + void FixedUpdate(float fixedDeltaTime); + void LateUpdate(float deltaTime); + + // 事件 + Event OnSceneLoaded; + Event OnSceneUnloaded; + Event OnActiveSceneChanged; + +private: + SceneManager() = default; + + std::vector> m_scenes; + Scene* m_activeScene = nullptr; + Scene* m_loadingScene = nullptr; + + std::unordered_map m_sceneNameMap; + std::function m_loadCallback; + bool m_loading = false; +}; + +} // namespace XCEngine +``` + +--- + +## 第四章 渲染系统 (Renderer) + +> **架构说明**: +> - **RenderGraph** - 高级渲染管线抽象,定义 Pass 之间的依赖关系和资源流 +> - **RenderContext** - 低级渲染上下文,管理 GPU 资源和执行具体的渲染命令 +> - 关系:RenderGraph 是声明式的渲染描述,RenderContext 是执行层 + +### 4.1 渲染系统架构 + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Rendering Pipeline │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌───────────────────────────────────────────────────────────────────────┐ │ +│ │ Render Pipeline Manager │ │ +│ └───────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌────────────────────────────────▼───────────────────────────────────────┐ │ +│ │ Render Graph Builder │ │ +│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ +│ │ │ Pass 1 │ │ Pass 2 │ │ Pass 3 │ │ Pass N │ │ │ +│ │ │ G-Buffer │ │ Lighting │ │ Shadow │ │ Post │ │ │ +│ │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │ │ +│ └───────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌────────────────────────────────▼───────────────────────────────────────┐ │ +│ │ Render Passes │ │ +│ │ │ │ +│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ +│ │ │ GBuffer │→ │ Shadow │→ │ Deferred │→ │ Forward │ │ │ +│ │ │ Pass │ │ Pass │ │ Lighting │ │ Pass │ │ │ +│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ +│ │ ↓ ↓ ↓ ↓ │ │ +│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ +│ │ │ Depth │ │ Shadow │ │ SSAO │ │ Alpha │ │ │ +│ │ │ Pre-Pass │ │ Update │ │ Pass │ │ Blend │ │ │ +│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ +│ │ ↓ │ │ +│ │ ┌────────────────────────────────────────────────────────────────┐ │ │ +│ │ │ Post-Processing │ │ │ +│ │ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ +│ │ │ │ SSAO │ │ SSR │ │ Bloom │ │ Tone │ │ FXAA │ │ │ │ +│ │ │ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │ │ │ +│ │ └────────────────────────────────────────────────────────────────┘ │ │ +│ └───────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌────────────────────────────────▼───────────────────────────────────────┐ │ +│ │ GPU Resources │ │ +│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ +│ │ │ Vertex │ │ Index │ │ Uniform │ │ Texture │ │ Render │ │ │ +│ │ │ Buffer │ │ Buffer │ │ Buffer │ │ Sampler │ │ Target │ │ │ +│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ +│ └───────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 4.2 渲染抽象层 + +```cpp +namespace XCEngine { +namespace Rendering { + +enum class ResourceState { + Undefined, + RenderTarget, + DepthStencil, + ShaderResource, + UnorderedAccess, + CopySrc, + CopyDst, + Present +}; + +struct ResourceDesc { + ResourceType type; + uint32_t width = 1; + uint32_t height = 1; + uint32_t depth = 1; + uint32_t mipLevels = 1; + uint32_t arraySize = 1; + Format format = Format::Unknown; + SampleCount sampleCount = SampleCount::Count1; + ResourceState initialState = ResourceState::Undefined; + bool cpuAccessible = false; + bool randomAccess = false; + + MemoryUsage memoryUsage = MemoryUsage::Default; + + String name; +}; + +class IRenderDevice { +public: + virtual ~IRenderDevice() = default; + + virtual const char* GetApiName() const = 0; + virtual const char* GetDriverVersion() const = 0; + virtual uint64_t GetDeviceId() const = 0; + virtual uint64_t GetVendorId() const = 0; + + virtual bool SupportsRaytracing() const = 0; + virtual bool SupportsMeshShaders() const = 0; + virtual bool SupportsVariableRateShading() const = 0; + virtual bool SupportsSamplerFeedback() const = 0; + virtual uint32_t GetMaxTextureSize() const = 0; + virtual uint32_t GetMaxUBOSize() const = 0; + virtual uint32_t GetMaxMSAA() const = 0; + + virtual std::unique_ptr CreateTexture(const ResourceDesc& desc) = 0; + virtual std::unique_ptr CreateBuffer(const ResourceDesc& desc, const void* initialData = nullptr) = 0; + virtual std::unique_ptr CreateShader(const ShaderDesc& desc) = 0; + virtual std::unique_ptr CreatePipeline(const PipelineDesc& desc) = 0; + virtual std::unique_ptr CreateRenderPass(const RenderPassDesc& desc) = 0; + + virtual ICommandQueue* GetGraphicsQueue() = 0; + virtual ICommandQueue* GetComputeQueue() = 0; + virtual ICommandQueue* GetCopyQueue() = 0; + + virtual std::unique_ptr CreateFence() = 0; + virtual IDescriptorHeap* CreateDescriptorHeap(const DescriptorHeapDesc& desc) = 0; + virtual std::unique_ptr CreateQueryHeap(const QueryHeapDesc& desc) = 0; +}; + +class ICommandList { +public: + virtual ~ICommandList() = default; + + virtual void TransitionBarrier(const IResource* resource, ResourceState newState) = 0; + virtual void UAVBarrier(const IResource* resource) = 0; + virtual void FlushBarriers() = 0; + + virtual void SetPipeline(const IPipeline* pipeline) = 0; + virtual void SetVertexBuffer(uint32_t slot, const IBuffer* buffer, uint64_t offset = 0) = 0; + virtual void SetIndexBuffer(const IBuffer* buffer, IndexType indexType, uint64_t offset = 0) = 0; + virtual void SetConstantBuffer(uint32_t slot, const IBuffer* buffer, uint64_t offset = 0) = 0; + virtual void SetShaderResource(uint32_t slot, const IResource* resource) = 0; + virtual void SetSampler(uint32_t slot, const ISampler* sampler) = 0; + + virtual void Draw(uint32_t vertexCount, uint32_t firstVertex = 0) = 0; + virtual void DrawIndexed(uint32_t indexCount, uint32_t firstIndex = 0, int32_t baseVertex = 0) = 0; + virtual void DrawInstanced(uint32_t vertexCountPerInstance, uint32_t instanceCount, + uint32_t firstVertex = 0, uint32_t firstInstance = 0) = 0; + virtual void DrawIndexedInstanced(uint32_t indexCountPerInstance, uint32_t instanceCount, + uint32_t firstIndex = 0, int32_t baseVertex = 0, uint32_t firstInstance = 0) = 0; + + virtual void Dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ) = 0; + + virtual void BuildAccelerationStructure(const RaytracingBuildDesc& desc) = 0; + virtual void SetRaytracingPipeline(const IPipeline* pipeline) = 0; + virtual void DispatchRays(const DispatchRaysDesc& desc) = 0; + + virtual void BeginRenderPass(const RenderPassBeginDesc& desc) = 0; + virtual void EndRenderPass() = 0; + + virtual void CopyResource(IResource* dst, const IResource* src) = 0; + virtual void CopyBuffer(IBuffer* dst, uint64_t dstOffset, const IBuffer* src, uint64_t srcOffset, uint64_t size) = 0; + + virtual void BeginQuery(IQueryHeap* heap, uint32_t index) = 0; + virtual void EndQuery(IQueryHeap* heap, uint32_t index) = 0; + + virtual void SetMarker(const char* name, uint32_t color) = 0; + virtual void BeginEvent(const char* name, uint32_t color) = 0; + virtual void EndEvent() = 0; +}; + +class RenderContext { +public: + // 前向声明 + class GBufferPass; + class LightingPass; + class ShadowPass; + class PostProcessPass; + + // 创建和销毁(支持多实例) + static RenderContext* Create(const RenderContextDesc& desc); + static void Destroy(RenderContext* context); + + // 获取主上下文(默认上下文,用于单窗口场景) + static RenderContext* GetMain(); + + void Initialize(const RenderContextDesc& desc); + void Shutdown(); + + IRenderDevice* GetDevice() { return m_device.get(); } + + void BeginFrame(); + void EndFrame(); + + ICommandList* GetMainCommandList() { return m_mainCommandList.get(); } + + void SetRenderTarget(const RenderTarget& target); + void SetViewport(const Viewport& viewport); + void SetScissorRect(const Rect& rect); + + void RenderScene(const SceneRenderDesc& desc); + void ApplyPostProcessing(const PostProcessDesc& desc); + + void CaptureFrame(const String& filePath); + void ToggleDebugView(); + +private: + std::unique_ptr m_device; + std::unique_ptr m_mainCommandList; + std::unique_ptr m_swapChain; + + std::unique_ptr m_gBufferPass; + std::unique_ptr m_lightingPass; + std::unique_ptr m_shadowPass; + std::unique_ptr m_postProcessPass; + + uint32_t m_frameIndex = 0; + uint64_t m_frameCount = 0; + + // 静态主上下文(用于 GetMain()) + static RenderContext* s_mainContext; +}; + +class RenderTexture : public IResource { +public: + uint32_t GetWidth() const { return m_width; } + uint32_t GetHeight() const { return m_height; } + uint32_t GetMipLevels() const { return m_mipLevels; } + Format GetFormat() const { return m_format; } + + void* GetNativeHandle() const { return m_nativeHandle; } + + IShaderResourceView* GetSRV() { return m_srv.get(); } + IRenderTargetView* GetRTV() { return m_rtv.get(); } + IDepthStencilView* GetDSV() { return m_dsv.get(); } + + void* Map(); + void Unmap(); + +private: + uint32_t m_width, m_height; + uint32_t m_mipLevels; + Format m_format; + void* m_nativeHandle = nullptr; + + std::unique_ptr m_srv; + std::unique_ptr m_rtv; + std::unique_ptr m_dsv; +}; + +class RenderBuffer : public IResource { +public: + uint64_t GetSize() const { return m_size; } + BufferUsage GetUsage() const { return m_usage; } + + void* GetNativeHandle() const { return m_nativeHandle; } + + void SetData(const void* data, uint64_t size, uint64_t offset = 0); + void* Map(); + void Unmap(); + +private: + uint64_t m_size; + BufferUsage m_usage; + void* m_nativeHandle = nullptr; +}; + +} +} +``` + +### 4.3 渲染图 (Render Graph) + +```cpp +namespace XCEngine { +namespace Rendering { + +class RenderGraphResource { +public: + RenderGraphResource() = default; + RenderGraphResource(const String& name); + + const String& GetName() const { return m_name; } + uint32_t GetIndex() const { return m_index; } + + bool IsValid() const { return m_index != UINT32_MAX; } + operator bool() const { return IsValid(); } + +private: + String m_name; + uint32_t m_index = UINT32_MAX; + friend class RenderGraph; +}; + +class RenderGraphPass { +public: + using ExecuteFn = std::function; + + RenderGraphPass(const String& name, PassType type); + + RenderGraphResource Read(const String& resourceName); + RenderGraphResource Write(const String& resourceName); + RenderGraphResource ReadWrite(const String& resourceName, ResourceState initialState, ResourceState finalState); + + void Execute(ExecuteFn&& fn); + void Execute() const; + + void SetDebugColor(const Color& color); + + const String& GetName() const { return m_name; } + PassType GetType() const { return m_type; } + const std::vector& GetReads() const { return m_reads; } + const std::vector& GetWrites() const { return m_writes; } + +private: + String m_name; + PassType m_type; + std::vector m_reads; + std::vector m_writes; + ExecuteFn m_executeFn; + Color m_debugColor; + + friend class RenderGraph; +}; + +class RenderGraph { +public: + RenderGraph(); + ~RenderGraph(); + + RenderGraphResource CreateTexture(const String& name, const TextureDesc& desc); + RenderGraphResource CreateBuffer(const String& name, const BufferDesc& desc); + + RenderGraphPass& AddPass(const String& name, PassType type); + + void Build(); + void Execute(ICommandList* commandList); + + void SetName(const String& name); + void Print() const; + void ExportToDot(const String& filePath) const; + + void Clear(); + +private: + void Compile(); + void Validate(); + void SortPasses(); + void AllocateResources(); + + struct ResourceInfo { + String name; + ResourceDesc desc; + ResourceState currentState; + uint32_t firstPassWrite = UINT32_MAX; + uint32_t lastPassRead = UINT32_MAX; + bool imported = false; + }; + + struct PassInfo { + String name; + PassType type; + std::vector reads; + std::vector writes; + std::function executeFn; + }; + + std::vector m_resources; + std::vector m_passes; + std::unordered_map m_resourceIndex; + + bool m_built = false; +}; + +} +} +``` + +--- + +## 第五章 资源系统 (Resource System) + +### 5.1 资源管理架构 + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Resource Management │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌───────────────────────────────────────────────────────────────────────┐ │ +│ │ Asset Database │ │ +│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ +│ │ │ GUID │ │ Path │ │ Meta │ │ │ +│ │ │ 映射表 │ │ 索引 │ │ 数据 │ │ │ +│ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ +│ └───────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌────────────────────────────────▼───────────────────────────────────────┐ │ +│ │ Resource Manager │ │ +│ │ ┌───────────────────────────────────────────────────────────────┐ │ │ +│ │ │ Resource Loader Registry │ │ │ +│ │ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ +│ │ │ │ Mesh │ │ Texture│ │ Audio │ │ Material│ │ Shader │ │ │ │ +│ │ │ │ Loader │ │ Loader │ │ Loader │ │ Loader │ │ Loader │ │ │ │ +│ │ │ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │ │ │ +│ │ └───────────────────────────────────────────────────────────────┘ │ │ +│ │ │ │ │ +│ │ ┌──────────────────────────▼────────────────────────────────────┐ │ │ +│ │ │ Resource Cache │ │ │ +│ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ +│ │ │ │ LRU Cache │ │ │ │ +│ │ │ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ │ +│ │ │ │ │ Resource│ │ Resource│ │ Resource│ │ Resource│ │ │ │ │ +│ │ │ │ │ 1 │ │ 2 │ │ 3 │ │ N │ │ │ │ │ +│ │ │ │ └────────┘ └────────┘ └────────┘ └────────┘ │ │ │ │ +│ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ +│ │ └───────────────────────────────────────────────────────────────┘ │ │ +│ └───────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌────────────────────────────────▼───────────────────────────────────────┐ │ +│ │ Import Pipeline │ │ +│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ +│ │ │ Import │→ │ Process │→ │ Cook │→ │ Package │→ │ Index │ │ │ +│ │ │ 导入 │ │ 处理 │ │ 烘焙 │ │ 打包 │ │ 索引 │ │ │ +│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ +│ └───────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### 5.2 资源系统实现 + +```cpp +namespace XCEngine { +namespace Resources { + +enum class ResourceType { + Unknown, + Mesh, + Texture, + Material, + Shader, + Audio, + Animation, + Skeleton, + Font, + Prefab, + Scene, + Script, + PhysicsMaterial, + NavMesh, + Video, + Custom +}; + +struct ResourceGUID { + static constexpr uint64_t INVALID = 0; + + uint64_t value = INVALID; + + bool IsValid() const { return value != INVALID; } + bool operator==(const ResourceGUID& other) const { return value == other.value; } + bool operator!=(const ResourceGUID& other) const { return value != other.value; } + + String ToString() const; + static ResourceGUID FromString(const String& str); + + struct Hash { + size_t operator()(const ResourceGUID& guid) const { + return std::hash{}(guid.value); + } + }; +}; + +class IResource { +public: + virtual ~IResource() = default; + + virtual ResourceType GetType() const = 0; + virtual const String& GetName() const = 0; + virtual ResourceGUID GetGUID() const = 0; + + virtual bool IsLoaded() const = 0; + virtual bool IsLoading() const = 0; + virtual float GetLoadingProgress() const = 0; + + virtual void AddRef() = 0; + virtual void Release() = 0; + virtual uint32_t GetRefCount() const = 0; + + virtual void Unload() = 0; +}; + +struct LoadRequest { + ResourceGUID guid; + ResourceType type; + std::function callback; + std::function progressCallback; + bool async = true; + uint32_t priority = 0; +}; + +class IResourceLoader { +public: + virtual ~IResourceLoader() = default; + + virtual ResourceType GetResourceType() const = 0; + virtual std::vector GetSupportedExtensions() const = 0; + + virtual bool CanLoad(const String& filePath) const = 0; + virtual bool Load(const String& filePath, IResource* resource) = 0; + virtual bool Save(const String& filePath, const IResource* resource) = 0; + + virtual std::unique_ptr CreateResource() = 0; +}; + +class ResourceRepository { +public: + void Initialize(const String& basePath); + void Shutdown(); + + std::unique_ptr LoadRaw(const String& filePath, size_t& outSize); + std::unique_ptr OpenStream(const String& filePath); + + bool FileExists(const String& filePath); + bool DirectoryExists(const String& dirPath); + std::vector GetFiles(const String& dirPath, const String& extension = ""); + + String GetFullPath(const String& relativePath); + String GetCachePath(); + String GetSourcePath(); + +private: + String m_basePath; + String m_cachePath; + String m_sourcePath; +}; + +class ResourceCache { +public: + explicit ResourceCache(size_t maxMemory); + ~ResourceCache(); + + void Initialize(); + void Shutdown(); + + void Add(const ResourceGUID& guid, IResource* resource); + IResource* Find(const ResourceGUID& guid); + void Remove(const ResourceGUID& guid); + void Clear(); + + void SetMaxMemory(size_t bytes); + size_t GetCurrentMemory() const; + size_t GetMaxMemory() const; + + void Touch(const ResourceGUID& guid); + void Evict(size_t bytesToFree); + + struct Stats { + uint32_t hitCount; + uint32_t missCount; + size_t memoryUsed; + size_t memoryReserved; + }; + const Stats& GetStats() const; + +private: + struct CacheEntry { + IResource* resource; + size_t memorySize; + uint64_t lastAccess; + }; + + std::unordered_map m_cache; + size_t m_maxMemory; + size_t m_currentMemory; + Stats m_stats; +}; + +class ResourceManager { +public: + static ResourceManager& Get(); + + void Initialize(const ResourceManagerConfig& config); + void Shutdown(); + + void RegisterLoader(std::unique_ptr loader); + IResourceLoader* GetLoader(ResourceType type) const; + IResourceLoader* GetLoaderForFile(const String& filePath) const; + + ResourceGUID Load(const String& filePath); + ResourceGUID LoadAsync(const String& filePath, const std::function& callback); + + template + std::shared_ptr Get(const ResourceGUID& guid); + + template + std::shared_ptr Get(const String& filePath); + + void AddRef(const ResourceGUID& guid); + void Release(const ResourceGUID& guid); + + ResourceGUID FindByPath(const String& path) const; + String GetPath(const ResourceGUID& guid) const; + + bool Reload(const ResourceGUID& guid); + void Unload(const ResourceGUID& guid); + void UnloadUnused(); + + void PrintStatistics(); + + void RebuildDatabase(); + void ScanDirectory(const String& dirPath); + +private: + ResourceManager() = default; + + std::unordered_map> m_loaders; + std::unordered_map, ResourceGUID::Hash> m_resources; + std::unordered_map m_pathToGUID; + std::unordered_map m_guidToPath; + + std::unique_ptr m_cache; + std::unique_ptr m_repository; + + std::unique_ptr m_assetDatabase; + + std::atomic m_nextGuid{1}; +}; + +template +class ResourcePtr { +public: + ResourcePtr() = default; + + explicit ResourcePtr(const ResourceGUID& guid) + : m_guid(guid), m_resource(ResourceManager::Get().Get(guid)) {} + + ResourcePtr(const ResourcePtr& other) + : m_guid(other.m_guid), m_resource(other.m_resource) {} + + ~ResourcePtr() { + if (m_guid.IsValid()) { + ResourceManager::Get().Release(m_guid); + } + } + + T* Get() const { return m_resource.get(); } + T* operator->() const { return m_resource.get(); } + T& operator*() const { return *m_resource; } + + bool IsValid() const { return m_resource != nullptr; } + explicit operator bool() const { return IsValid(); } + + const ResourceGUID& GetGUID() const { return m_guid; } + +private: + ResourceGUID m_guid; + std::shared_ptr m_resource; +}; + +} +} +``` + +--- + +## 第六章 场景系统 (Scene System) + +> **架构说明**: Scene是Unity风格的场景,直接管理GameObject列表(没有World中间层),负责场景生命周期管理、资源加载和序列化。 + +### 6.1 场景管理 + +```cpp +namespace XCEngine { +namespace Scene { + +// 注意:GameObject和Transform定义在Components命名空间中 +// Transform是GameObject的内置组件,包含父子层级关系 + +enum class SceneLoadFlags { + None = 0, + Async = 1 << 0, + Additive = 1 << 1, + Single = 1 << 2, + DontLoadAudio = 1 << 3, + DontCreatePhysics = 1 << 4, + SubScene = 1 << 5 +}; + +inline SceneLoadFlags operator|(SceneLoadFlags a, SceneLoadFlags b) { + return static_cast(static_cast(a) | static_cast(b)); +} + +inline SceneLoadFlags& operator|=(SceneLoadFlags& a, SceneLoadFlags b) { + a = a | b; + return a; +} + +inline SceneLoadFlags operator&(SceneLoadFlags a, SceneLoadFlags b) { + return static_cast(static_cast(a) & static_cast(b)); +} + +inline SceneLoadFlags& operator&=(SceneLoadFlags& a, SceneLoadFlags b) { + a = a & b; + return a; +} + +inline bool HasFlag(SceneLoadFlags flags, SceneLoadFlags flag) { + return (static_cast(flags) & static_cast(flag)) != 0; +} + +// 注意:SceneManager 定义在 XCEngine 命名空间中(第三章 3.5 节) +// 此处只保留场景相关的辅助类型和序列化器 + +// 场景序列化器 +// 支持 JSON 和 Binary 两种格式 +class SceneSerializer { +public: + // 序列化格式 + enum class Format { + JSON, + Binary + }; + + // 序列化到文件 + static void Serialize(const Scene& scene, const String& filePath, Format format = Format::JSON); + static std::unique_ptr Deserialize(const String& filePath); + + // JSON 序列化 (使用已存在的 Core 命名空间中的 JSON 库) + static void SerializeToJson(const Scene& scene, Core::JsonDocument& doc); + static void DeserializeFromJson(Scene& scene, const Core::JsonDocument& doc); + + // Binary 序列化 (使用 Core::IStream) + static void SerializeToBinary(const Scene& scene, Core::IStream& stream); + static std::unique_ptr DeserializeFromBinary(Core::IStream& stream); + +private: + static void SerializeGameObject(const GameObject& gameObject, Core::JsonValue& parent); + static void DeserializeGameObject(GameObject& gameObject, const Core::JsonValue& data); + + static void SerializeComponent(uint32_t componentTypeId, const void* component, Core::JsonValue& parent); + static void DeserializeComponent(uint32_t componentTypeId, const GameObject& gameObject, const Core::JsonValue& data); +}; + +// ============================================================================ +// 序列化辅助类型 (需要在 Core 命名空间中定义) +// ============================================================================ + +namespace Core { + +// 流接口 +class IStream { +public: + virtual ~IStream() = default; + + virtual bool IsValid() const = 0; + virtual size_t GetPosition() const = 0; + virtual size_t GetSize() const = 0; + + virtual size_t Read(void* buffer, size_t size) = 0; + virtual size_t Write(const void* buffer, size_t size) = 0; + + virtual void Seek(size_t position) = 0; + virtual void Skip(size_t bytes) = 0; + virtual void Flush() = 0; + + virtual bool IsReading() const = 0; + virtual bool IsWriting() const = 0; +}; + +// JSON 文档 +class JsonDocument { +public: + JsonDocument(); + ~JsonDocument(); + + void Parse(const String& json); + void Parse(const char* json, size_t length); + + JsonValue& GetRoot(); + const JsonValue& GetRoot() const; + + String ToString() const; + + bool HasParseError() const; + String GetParseError() const; +}; + +// JSON 值 +class JsonValue { +public: + enum class Type { + Null, + Bool, + Int, + Float, + String, + Array, + Object + }; + + JsonValue(); + JsonValue(bool value); + JsonValue(int32_t value); + JsonValue(int64_t value); + JsonValue(float value); + JsonValue(double value); + JsonValue(const String& value); + JsonValue(const char* value); + ~JsonValue(); + + Type GetType() const { return m_type; } + + // 值的获取 + bool GetBool() const; + int32_t GetInt() const; + int64_t GetInt64() const; + float GetFloat() const; + double GetDouble() const; + const String& GetString() const; + + // 数组/对象访问 + size_t GetSize() const; + JsonValue& operator[](size_t index); + const JsonValue& operator[](size_t index) const; + JsonValue& operator[](const String& key); + const JsonValue& operator[](const String& key) const; + + bool Has(const String& key) const; + + // 修改 + JsonValue& SetBool(bool value); + JsonValue& SetInt(int32_t value); + JsonValue& SetFloat(float value); + JsonValue& SetString(const String& value); + + JsonValue& AddArrayElement(); + JsonValue& AddObjectMember(const String& key); + + void Clear(); + +private: + Type m_type = Type::Null; + // ... 具体成员 +}; + +} // namespace Core + +} +} +``` + +--- + +## 第七章 物理系统 (Physics) + +### 7.1 物理系统 + +```cpp +namespace XCEngine { +namespace Physics { + +// 碰撞检测查询标志 +enum class QueryFlags : uint32_t { + None = 0, + Colliders = 1 << 0, + Rigidodies = 1 << 1, + Transforms = 1 << 2, + All = Colliders | Rigidodies | Transforms +}; + +// 力学模式 (类Unity ForceMode) +enum class ForceMode : uint8_t { + Force = 0, // 持续力 (质量单位) + Acceleration = 1, // 加速度 (无质量单位) + Impulse = 2, // 瞬时冲量 (质量单位) + VelocityChange = 3 // 速度变化 (无质量单位) +}; + +enum class CollisionShapeType { + Sphere, + Box, + Capsule, + ConvexMesh, + ConcaveMesh, + Heightfield, + Compound +}; + +struct CollisionLayer { + static constexpr uint32_t MaxLayers = 32; + static constexpr uint32_t Default = 0; + + uint32_t id; + String name; + uint32_t mask; +}; + +struct PhysicsMaterial { + float friction = 0.5f; + float restitution = 0.0f; + float frictionCombine = 0; + float restitutionCombine = 0; + bool isTrigger = false; + + float staticFriction = 0.5f; + float dynamicFriction = 0.5f; +}; + +struct RaycastHit { + GameObject* gameObject; + Vector3 point; + Vector3 normal; + float distance; + Vector2 uv; + int32_t faceIndex; + float fraction; + + ColliderComponent* collider = nullptr; +}; + +// 碰撞信息 (类Unity Collision) +struct Collision { + GameObject* gameObject = nullptr; + ColliderComponent* collider = nullptr; + RigidBodyComponent* rigidBody = nullptr; + + Vector3 relativeVelocity; + Vector3 contactPoint; + Vector3 contactNormal; + + std::vector contacts; + std::vector normals; +}; + +// 2D碰撞信息 (类Unity Collision2D) +struct Collision2D { + GameObject* gameObject = nullptr; + Collider2DComponent* collider = nullptr; + RigidBody2DComponent* rigidBody = nullptr; + + Vector2 relativeVelocity; + Vector2 contactPoint; + Vector2 contactNormal; + + std::vector contacts; + std::vector normals; + + float fraction = 0.0f; + int32_t faceID = 0; +}; + +// 2D碰撞体组件 (类Unity Collider2D) +class Collider2DComponent : public Component { +public: + void Awake() override; + void Start() override; + + enum class ShapeType : uint8_t { + Box, + Circle, + Capsule, + Polygon, + Edge + }; + + void SetShapeType(ShapeType type) { m_shapeType = type; } + ShapeType GetShapeType() const { return m_shapeType; } + + void SetOffset(const Vector2& offset) { m_offset = offset; } + Vector2 GetOffset() const { return m_offset; } + + void SetDensity(float density) { m_density = density; } + float GetDensity() const { return m_density; } + + void SetIsTrigger(bool trigger) { m_isTrigger = trigger; } + bool IsTrigger() const { return m_isTrigger; } + + void SetUsedByEffector(bool use) { m_usedByEffector = use; } + bool IsUsedByEffector() const { return m_usedByEffector; } + +private: + ShapeType m_shapeType = ShapeType::Box; + Vector2 m_offset = Vector2::Zero(); + float m_density = 1.0f; + bool m_isTrigger = false; + bool m_usedByEffector = false; + + void* m_physicsHandle = nullptr; +}; + +// 2D刚体组件 (类Unity Rigidbody2D) +class RigidBody2DComponent : public Component { +public: + void Awake() override; + void Start() override; + void FixedUpdate() override; + + enum class BodyType : uint8_t { + Dynamic, + Kinematic, + Static + }; + + enum class InterpolateMode : uint8_t { + None, + Interpolate, + Extrapolate + }; + + void SetBodyType(BodyType type) { m_bodyType = type; } + BodyType GetBodyType() const { return m_bodyType; } + + void SetMass(float mass) { m_mass = mass; } + float GetMass() const { return m_mass; } + + void SetLinearVelocity(const Vector2& velocity); + Vector2 GetLinearVelocity() const; + + void SetAngularVelocity(float velocity); + float GetAngularVelocity() const; + + void AddForce(const Vector2& force, ForceMode mode = ForceMode::Force); + void AddForceAtPosition(const Vector2& force, const Vector2& position, ForceMode mode = ForceMode::Force); + + void SetGravityScale(float scale) { m_gravityScale = scale; } + float GetGravityScale() const { return m_gravityScale; } + + void SetIsKinematic(bool kinematic) { m_kinematic = kinematic; } + bool IsKinematic() const { return m_kinematic; } + + void SetInterpolateMode(InterpolateMode mode) { m_interpolateMode = mode; } + InterpolateMode GetInterpolateMode() const { return m_interpolateMode; } + + void* GetPhysicsHandle() const { return m_physicsHandle; } + void SetPhysicsHandle(void* handle) { m_physicsHandle = handle; } + +private: + BodyType m_bodyType = BodyType::Dynamic; + float m_mass = 1.0f; + Vector2 m_linearVelocity; + float m_angularVelocity = 0.0f; + float m_gravityScale = 1.0f; + bool m_kinematic = false; + InterpolateMode m_interpolateMode = InterpolateMode::None; + + void* m_physicsHandle = nullptr; +}; + +struct CollisionEvent { + GameObject* gameObjectA; + GameObject* gameObjectB; + Vector3 point; + Vector3 normal; + Vector3 relativeVelocity; + + enum class Type { + Enter, + Stay, + Exit + }; + Type type; +}; + +class PhysicsWorld { +public: + PhysicsWorld(); + ~PhysicsWorld(); + + void Initialize(const PhysicsWorldDesc& desc); + void Shutdown(); + + void Simulate(float deltaTime); + void SetGravity(const Vector3& gravity); + Vector3 GetGravity() const { return m_gravity; } + + // 物理组件注册(替代直接 SyncWithScene,通过组件系统同步) + void RegisterRigidBody(RigidBodyComponent* component); + void UnregisterRigidBody(RigidBodyComponent* component); + void RegisterCollider(ColliderComponent* component); + void UnregisterCollider(ColliderComponent* component); + + bool Raycast(const Ray& ray, float maxDistance, RaycastHit& hit, + uint32_t layerMask = 0xFFFFFFFF, QueryFlags flags = QueryFlags::None); + bool RaycastMultiple(const Ray& ray, float maxDistance, std::vector& hits, + uint32_t layerMask = 0xFFFFFFFF, QueryFlags flags = QueryFlags::None); + + bool CheckSphere(const Sphere& sphere, uint32_t layerMask = 0xFFFFFFFF); + bool CheckBox(const Box& box, uint32_t layerMask = 0xFFFFFFFF); + bool CheckCapsule(const Vector3& start, const Vector3& end, float radius, + uint32_t layerMask = 0xFFFFFFFF); + + bool SphereCast(const Sphere& sphere, const Vector3& direction, float maxDistance, + RaycastHit& hit, uint32_t layerMask = 0xFFFFFFFF); + + std::vector OverlapSphere(const Sphere& sphere, uint32_t layerMask = 0xFFFFFFFF); + std::vector OverlapBox(const Box& box, uint32_t layerMask = 0xFFFFFFFF); + + // 使用 RigidBodyComponent* 代替 GameObject*,通过组件内部的句柄操作,避免悬空指针 + void AddForce(RigidBodyComponent* component, const Vector3& force, ForceMode mode = ForceMode::Force); + void AddForceAtPosition(RigidBodyComponent* component, const Vector3& force, const Vector3& position, + ForceMode mode = ForceMode::Force); + void AddTorque(RigidBodyComponent* component, const Vector3& torque, ForceMode mode = ForceMode::Force); + + void SetLinearVelocity(RigidBodyComponent* component, const Vector3& velocity); + void SetAngularVelocity(RigidBodyComponent* component, const Vector3& velocity); + Vector3 GetLinearVelocity(RigidBodyComponent* component) const; + Vector3 GetAngularVelocity(RigidBodyComponent* component) const; + + void SetKinematic(RigidBodyComponent* component, bool kinematic); + + // Joint 由 JointComponent 组件管理,不再由 PhysicsWorld 直接创建 + + Event OnCollisionEnter; + Event OnCollisionStay; + Event OnCollisionExit; + Event OnTriggerEnter; + Event OnTriggerStay; + Event OnTriggerExit; + + void DebugDraw(); + void SetDebugDrawEnabled(bool enabled); + +private: + void* m_physicsBackend = nullptr; + + Vector3 m_gravity = Vector3(0, -9.81f, 0); + + std::vector m_collisionEvents; + std::vector m_triggerEvents; + + bool m_debugDrawEnabled = false; +}; + +class CharacterControllerComponent : public Component { +public: + void Awake() override; + void Update(float deltaTime) override; + void OnDestroy() override; + + void Initialize(const CharacterControllerDesc& desc); + + void Move(const Vector3& displacement); + void SetVelocity(const Vector3& velocity); + Vector3 GetVelocity() const { return m_velocity; } + + bool IsGrounded() const { return m_grounded; } + Vector3 GetGroundNormal() const { return m_groundNormal; } + GameObject* GetGroundObject() const { return m_groundObject; } + + void Jump(const Vector3& jumpForce); + void SetJumpEnabled(bool enabled); + + void SetSlopeLimit(float angle); + void SetStepOffset(float height); + void SetSkinWidth(float width); + + bool DetectCollision(const Vector3& position, const Vector3& direction, float distance); + +private: + void UpdateGroundStatus(); + void HandleCollision(); + + Vector3 m_velocity = Vector3::Zero(); + Vector3 m_pendingForces = Vector3::Zero(); + + float m_slopeLimit = 45.0f; + float m_stepOffset = 0.5f; + float m_skinWidth = 0.02f; + float m_minDistance = 0.1f; + + bool m_grounded = false; + bool m_jumpEnabled = true; + Vector3 m_groundNormal = Vector3::Up(); + GameObject* m_groundObject = nullptr; + + uint32_t m_layer = 0; + uint32_t m_collisionMask = 0xFFFFFFFF; +}; + +} +} +``` + +--- + +## 第八章 音频系统 (Audio) + +> **架构说明**: Unity风格的音频系统。音频源和监听器都是挂载在GameObject上的组件。 +> AudioEngine是底层实现,提供音频解码、混音、空间化等功能。 + +### 8.1 音频系统 + +```cpp +namespace XCEngine { +namespace Audio { + +// 音频格式 +enum class AudioFormat { + Unknown, + WAV, + OGG, + MP3, + FLAC, + AAC +}; + +// 音频片段 (资源) +class AudioClip : public IResource { +public: + AudioClip(); + ~AudioClip(); + + const String& GetName() const override { return m_name; } + ResourceType GetType() const override { return ResourceType::Audio; } + ResourceGUID GetGUID() const override { return m_guid; } + + bool IsLoaded() const override { return m_loaded; } + bool IsLoading() const override { return m_loading; } + float GetLoadingProgress() const override { return m_loadProgress; } + + const uint8_t* GetData() const { return m_data.get(); } + size_t GetDataSize() const { return m_dataSize; } + uint32_t GetSampleRate() const { return m_sampleRate; } + uint32_t GetChannels() const { return m_channels; } + uint32_t GetBitsPerSample() const { return m_bitsPerSample; } + float GetDuration() const { return m_duration; } + + AudioFormat GetFormat() const { return m_format; } + +private: + String m_name; + ResourceGUID m_guid; + + std::unique_ptr m_data; + size_t m_dataSize = 0; + + uint32_t m_sampleRate = 44100; + uint32_t m_channels = 2; + uint32_t m_bitsPerSample = 16; + float m_duration = 0.0f; + + AudioFormat m_format = AudioFormat::Unknown; + + bool m_loaded = false; + bool m_loading = false; + float m_loadProgress = 0.0f; + + friend class AudioEngine; +}; + +// 音频总线 (混音器) +class AudioBus { +public: + AudioBus(const String& name, AudioBus* parent = nullptr); + + void SetVolume(float volume); + float GetVolume() const { return m_volume; } + + void SetMute(bool mute); + bool IsMuted() const { return m_muted; } + + void SetBypassEffects(bool bypass); + bool IsBypassingEffects() const { return m_bypassEffects; } + + void AddEffect(AudioEffect* effect); + void RemoveEffect(AudioEffect* effect); + +private: + String m_name; + AudioBus* m_parent = nullptr; + std::vector m_children; + std::vector> m_effects; + + float m_volume = 1.0f; + bool m_muted = false; + bool m_bypassEffects = false; +}; + +// 音频引擎 - 底层实现 (不对外直接使用) +class AudioEngine { +public: + static AudioEngine& Get(); + + void Initialize(const AudioEngineConfig& config); + void Shutdown(); + + const char* GetDeviceName() const; + uint32_t GetSpeakerCount() const; + + void Update(float deltaTime); + + // 资源管理 + std::shared_ptr LoadClip(const String& filePath); + void UnloadClip(AudioClip* clip); + + // 混音器 + AudioBus* GetMasterBus() { return m_masterBus.get(); } + AudioBus* GetBus(const String& path); + AudioBus* CreateBus(const String& path); + + // 内部音频源管理 (由 AudioSystem 使用) + struct InternalSource { + uint64_t id = 0; + void* handle = nullptr; // 底层音频引擎句柄 + }; + + InternalSource CreateInternalSource(); + void DestroyInternalSource(InternalSource source); + void SetSourceClip(InternalSource source, AudioClip* clip); + void PlaySource(InternalSource source); + void StopSource(InternalSource source); + void PauseSource(InternalSource source); + void SetSourceVolume(InternalSource source, float volume); + void SetSourcePitch(InternalSource source, float pitch); + void SetSourcePosition(InternalSource source, const Vector3& position); + void SetSourceLoop(InternalSource source, bool loop); + bool IsSourcePlaying(InternalSource source); + + // 监听器管理 - Unity 限制只能有一个 AudioListener + void SetListenerComponent(AudioListenerComponent* listener); + AudioListenerComponent* GetListenerComponent() const { return m_listenerComponent; } + + void SetListenerPosition(const Vector3& position); + void SetListenerVelocity(const Vector3& velocity); + void SetListenerOrientation(const Vector3& forward, const Vector3& up); + void SetListenerDopplerFactor(float factor); + + struct Stats { + uint32_t activeVoices; + uint32_t totalVoices; + uint32_t playingSources; + uint32_t cpuUsage; + size_t memoryUsage; + }; + const Stats& GetStats() const { return m_stats; } + +private: + AudioEngine() = default; + + std::unique_ptr m_masterBus; + + std::unordered_map> m_loadedClips; + std::vector m_activeSources; + uint64_t m_nextSourceId = 1; + + // 监听器状态 + Vector3 m_listenerPosition; + Vector3 m_listenerVelocity; + Vector3 m_listenerForward = Vector3::Forward(); + Vector3 m_listenerUp = Vector3::Up(); + float m_listenerDopplerFactor = 1.0f; + + // 限制只能有一个 AudioListener + AudioListenerComponent* m_listenerComponent = nullptr; + + Stats m_stats; + + void* m_backend = nullptr; // FMOD / Wwise / OpenAL +}; + +} // namespace Audio +} // namespace XCEngine +``` + +--- + +## 第十章 动画系统 (Animation) + +### 10.1 动画系统架构 + +```cpp +namespace XCEngine { +namespace Animation { + +// 动画曲线 +struct AnimationCurve { + std::vector> floatKeys; + std::vector> vector3Keys; + std::vector> quaternionKeys; + std::vector> colorKeys; + + // 具体类型的求值方法 + float EvaluateFloat(float time, float defaultValue = 0.0f) const; + Vector3 EvaluateVector3(float time, const Vector3& defaultValue = Vector3::Zero()) const; + Quaternion EvaluateQuaternion(float time, const Quaternion& defaultValue = Quaternion::Identity()) const; + Color EvaluateColor(float time, const Color& defaultValue = Color::White) const; + + // 具体类型的 Key 操作 + void AddKeyFloat(float time, float value); + void AddKeyVector3(float time, const Vector3& value); + void AddKeyQuaternion(float time, const Quaternion& value); + void AddKeyColor(float time, const Color& value); + + void RemoveKeyFloat(float time); + void RemoveKeyVector3(float time); + void RemoveKeyQuaternion(float time); + void RemoveKeyColor(float time); +}; + +// 动画片段 +struct AnimationClip : public IResource { + float duration = 0.0f; + float sampleRate = 30.0f; + bool loop = false; + + // 轨道 + struct Track { + String path; // 目标路径 e.g., "Root/Child/Arm" + enum Type { Position, Rotation, Scale, Float, Int, Bool, Trigger } type; + AnimationCurve curve; + }; + + std::vector tracks; + + // 事件 + struct Event { + float time; + String functionName; + String stringParameter; + float floatParameter; + int intParameter; + }; + std::vector events; +}; + +// 骨骼 +struct Bone { + String name; + int32 parentIndex = -1; + Matrix4x4 localMatrix; + Matrix4x4 worldMatrix; + Vector3 position; + Quaternion rotation; + Vector3 scale; +}; + +// 骨架 +struct Skeleton : public IResource { + std::vector bones; + int32 rootBoneIndex = -1; + + int32 FindBone(const String& name) const; + const Bone& GetBone(int32 index) const; + Matrix4x4 GetBoneMatrix(int32 index) const; +}; + +// 蒙皮数据 +struct SkinningData { + std::vector bindPoses; + std::vector boneIndices; + std::vector boneWeights; +}; + +// 动画状态机 +class AnimatorStateMachine { +public: + struct State { + String name; + AnimationClip* clip = nullptr; + float speed = 1.0f; + float cycleOffset = 0.0f; + + std::vector transitions; + }; + + struct Transition { + String targetState; + float exitTime = 0.0f; + float duration = 0.0f; + + enum class ConditionMode { + If, + IfNot, + Greater, + Less, + Equals + }; + + struct Condition { + String parameter; + ConditionMode mode; + float threshold; + }; + std::vector conditions; + }; + + struct Parameter { + enum Type { Float, Int, Bool, Trigger } type; + String name; + }; + + // 状态管理 + void AddState(const String& name); + void AddTransition(const String& from, const String& to, const Transition& transition); + void AddParameter(const Parameter& param); + + // 播放控制 + void Play(const String& stateName); + void CrossFade(const String& stateName, float duration); + void Stop(); + + // 参数 + void SetFloat(const String& name, float value); + void SetInt(const String& name, int32 value); + void SetBool(const String& name, bool value); + void SetTrigger(const String& name); + + float GetFloat(const String& name) const; + int32 GetInt(const String& name) const; + bool GetBool(const String& name) const; + + // 动画层级 + void AddLayer(const String& name, float weight = 1.0f); + void SetLayerWeight(const String& name, float weight); + +private: + std::vector m_states; + std::vector m_parameters; + std::unordered_map m_stateIndices; + + String m_currentState; + String m_previousState; + float m_currentTime = 0.0f; +}; + +// 动画器组件 - 继承Component(类Unity Animator) +class AnimatorComponent : public Component { +public: + void Awake() override; + void Start() override; + void Update(float deltaTime) override; + void OnDestroy() override; + + void SetSkeleton(Skeleton* skeleton); + Skeleton* GetSkeleton() const { return m_skeleton; } + + // 播放控制 + void Play(const String& stateName); + void CrossFade(const String& stateName, float duration); + void PlayInFixedTime(const String& stateName, float normalizedTime); + + bool IsPlaying() const; + float GetCurrentAnimationTime() const; + float GetCurrentAnimationLength() const; + + // 层 + void AddLayer(const String& name, float weight); + void SetLayerWeight(const String& name, float weight); + + // 参数 + void SetFloat(const String& name, float value); + void SetInteger(const String& name, int32 value); + void SetBool(const String& name, bool value); + void SetTrigger(const String& name); + + // 根运动 + void SetApplyRootMotion(bool apply) { m_applyRootMotion = apply; } + bool GetApplyRootMotion() const { return m_applyRootMotion; } + + Vector3 GetRootPosition() const { return m_rootPosition; } + Quaternion GetRootRotation() const { return m_rootRotation; } + +private: + Skeleton* m_skeleton = nullptr; + std::unique_ptr m_stateMachine; + bool m_useGPUAnimation = false; + Buffer* m_boneMatricesBuffer = nullptr; + bool m_applyRootMotion = false; + Vector3 m_rootPosition; + Quaternion m_rootRotation; +}; + +// 动画系统管理器 (处理GPU蒙皮、事件等) +class AnimationSystem { +public: + static AnimationSystem& Get(); + + void Initialize(); + void Shutdown(); + + void Update(float deltaTime); + + void UpdateGPUBuffers(AnimatorComponent* animator); + void ProcessAnimationEvents(AnimatorComponent* animator, float prevTime, float currentTime); + +private: + void EvaluateState(AnimatorComponent* animator, float time, + std::vector& boneMatrices); + void BlendStates(AnimatorComponent* animator, float blendWeight, + const std::vector& from, + const std::vector& to, + std::vector& output); +}; + + // GPU 蒙皮 + void UpdateGPUBuffers(AnimatorComponent* animator); + + // 事件触发 + void ProcessAnimationEvents(AnimatorComponent* animator, float prevTime, float currentTime); + +private: + void EvaluateState(AnimatorComponent* animator, float time, + std::vector& boneMatrices); + void BlendStates(AnimatorComponent* animator, float blendWeight, + const std::vector& from, + const std::vector& to, + std::vector& output); +}; + +// Blend Shape +struct BlendShape { + String name; + std::vector vertices; + std::vector normals; + std::vector tangents; +}; + +struct BlendShapeFrame { + float weight = 0.0f; + std::vector deltaVertices; + std::vector deltaNormals; + std::vector deltaTangents; +}; + +struct BlendShapeData { + std::vector shapes; + std::vector frames; +}; + +// 程序化动画 +namespace ProceduralAnimation { + +class IKChain { +public: + void SetJoints(const std::vector& joints); + void Solve(const Vector3& target); + + void SetPoleVector(const Vector3& pole); + void SetIterations(int32 iterations); + +private: + std::vector m_joints; + Vector3 m_poleVector; + int32_t m_iterations = 10; +}; + +class CCDIK : public IKChain { +public: + void Solve(const Vector3& target) override; +}; + +class FABRIK : public IKChain { +public: + void Solve(const Vector3& target) override; + +private: + void ForwardReach(const Vector3& target); + void BackwardReach(const Vector3& base); + void SolveConstraints(); +}; + +} // namespace ProceduralAnimation +} // namespace Animation +} // namespace XCEngine +``` + +--- + +## 第十一章 粒子系统 (Particle System) + +### 11.1 粒子系统架构 + +```cpp +namespace XCEngine { +namespace Particles { + +// 粒子数据 - 粒子系统使用SoA布局以优化SIMD性能(这是性能关键路径的例外) +struct Particle { + Vector3 position; + Vector3 velocity; + Vector3 acceleration; + + Quaternion rotation; + float rotationSpeed; + + float size; + float lifetime; + float age; + + Color color; + float alpha; + + uint32_t seed; + bool alive; +}; + +// 粒子发射器 +class ParticleEmitter { +public: + // 发射模式 + enum class EmitMode { + Continuous, + Burst, + Distance + }; + + // 形状 + enum class ShapeType { + Sphere, + Box, + Cone, + Circle, + Edge, + MeshSurface, + MeshVolume + }; + + // 发射参数 + float rate = 10.0f; + int maxParticles = 1000; + float lifetime = 5.0f; + + // 初始速度 + Vector3 velocityMin = Vector3(-1, 1, -1); + Vector3 velocityMax = Vector3(1, 1, 1); + float speedMin = 1.0f; + float speedMax = 5.0f; + + // 初始变换 + float startSizeMin = 0.1f; + float startSizeMax = 0.5f; + float startRotationMin = 0.0f; + float startRotationMax = 360.0f; + Color startColor = Color::White; + + // 形状 + ShapeType shape = ShapeType::Sphere; + float shapeRadius = 1.0f; + float shapeAngle = 25.0f; + Vector3 shapeBoxSize = Vector3::One(); + + // 发射 + EmitMode emitMode = EmitMode::Continuous; + int burstCount = 10; + float burstInterval = 1.0f; +}; + +// 粒子系统组件 - 继承Component(类Unity ParticleSystem) +class ParticleSystemComponent : public Component { +public: + void Awake() override; + void Start() override; + void Update(float deltaTime) override; + void OnDestroy() override; + + // 播放控制(Unity 风格) + void Play(); + void Stop(); + void Pause(); + void Resume(); + void Clear(); + + bool IsPlaying() const { return m_isPlaying && !m_isPaused; } + bool IsPaused() const { return m_isPaused; } + bool IsStopped() const { return !m_isPlaying; } + + void SetLoop(bool loop) { m_loop = loop; } + bool GetLoop() const { return m_loop; } + + void SetEmitRate(float rate) { m_emitter.rate = rate; } + float GetEmitRate() const { return m_emitter.rate; } + + void SetLifetime(float lifetime) { m_emitter.lifetime = lifetime; } + float GetLifetime() const { return m_emitter.lifetime; } + + void SetStartSpeed(float speed) { m_emitter.speedMin = m_emitter.speedMax = speed; } + float GetStartSpeed() const { return m_emitter.speedMin; } + + void SetStartSize(float size) { m_emitter.startSizeMin = m_emitter.startSizeMax = size; } + float GetStartSize() const { return m_emitter.startSizeMin; } + + void SetStartColor(const Color& color) { m_emitter.startColor = color; } + Color GetStartColor() const { return m_emitter.startColor; } + +private: + ParticleEmitter m_emitter; + bool m_isPlaying = false; + bool m_isPaused = false; + bool m_loop = true; + float m_simulationSpeed = 1.0f; + float m_startDelay = 0.0f; + uint32_t m_randomSeed = 0; +}; + +// GPU 粒子系统 +class GPUParticleSystem { +public: + void Initialize(uint32_t maxParticles); + void Shutdown(); + + void Update(float deltaTime, const ParticleSystemComponent& config); + void Render(RenderContext& context); + + // GPU 缓冲区 + Buffer* GetPositionBuffer() { return m_positionBuffer.get(); } + Buffer* GetVelocityBuffer() { return m_velocityBuffer.get(); } + Buffer* GetColorBuffer() { return m_colorBuffer.get(); } + +private: + struct GPUParticle { + Vector4 position; // w = size + Vector4 velocity; // w = lifetime + Vector4 color; // w = rotation + }; + + uint32_t m_maxParticles = 0; + + std::unique_ptr m_positionBuffer; + std::unique_ptr m_velocityBuffer; + std::unique_ptr m_colorBuffer; + std::unique_ptr m_indexBuffer; + + ComputePipeline m_updatePipeline; +}; + +// 粒子系统管理器 +class ParticleSystemManager { +public: + static ParticleSystemManager& Get(); + + void Initialize(); + void Shutdown(); + + void Update(float deltaTime); + void Render(RenderContext& context); + + // 发射器 + ParticleEmitter* CreateEmitter(); + void DestroyEmitter(ParticleEmitter* emitter); + + // GPU 粒子 + GPUParticleSystem* GetGPUParticleSystem() { return &m_gpuSystem; } + +private: + std::vector> m_emitters; + GPUParticleSystem m_gpuSystem; +}; + +// VFX Graph 集成 +namespace VFXGraph { + +class VFXGraphAsset : public IResource { +public: + // VFX Graph 描述 +}; + +class VFXGraphComponent : public Component { +public: + void Update(float deltaTime) override; + + VFXGraphAsset* asset = nullptr; + + std::unordered_map floatParameters; + std::unordered_map vector3Parameters; + std::unordered_map colorParameters; + std::unordered_map boolParameters; + + void SetFloat(const String& name, float value); + void SetVector3(const String& name, const Vector3& value); + void SetColor(const String& name, const Color& value); + void SetBool(const String& name, bool value); + + void Play(); + void Stop(); + void Pause(); + void SetSeed(uint32_t seed); +}; + +} // namespace VFXGraph +} // namespace Particles +} // namespace XCEngine +``` + +--- + +## 第十二章 网络系统 (Networking) + +### 12.1 网络系统架构 + +```cpp +namespace XCEngine { +namespace Networking { + +// 网络模式 +enum class NetworkMode { + Offline, + Host, + Client, + Server +}; + +// 传输层 +enum class TransportProtocol { + UDP, + TCP, + WebSocket +}; + +// 网络消息 +struct NetworkMessage { + uint32_t type; + uint32_t channel; + uint32_t senderId; + uint64_t sequence; + uint64_t timestamp; + std::vector data; +}; + +// 消息类型 +enum class MessageType : uint32_t { + // 内置 + Connect = 1, + Disconnect = 2, + Heartbeat = 3, + Ack = 4, + + // 游戏 + Spawn = 100, + Despawn = 101, + TransformUpdate = 102, + ComponentUpdate = 103, + RPC = 104, + SceneChange = 105, +}; + +// 网络通道 +enum class NetworkChannel { + Reliable, + Unreliable, + Voice, + Raw +}; + +// 网络连接 +class NetworkConnection { +public: + uint32_t GetId() const { return m_id; } + const String& GetAddress() const { return m_address; } + float GetRoundTripTime() const { return m_rtt; } + + bool IsConnected() const { return m_connected; } + + void Send(uint32_t type, const void* data, size_t size, NetworkChannel channel); + void Disconnect(); + +private: + uint32_t m_id = 0; + String m_address; + bool m_connected = false; + float m_rtt = 0.0f; +}; + +// 网络玩家 +struct NetworkPlayer { + uint32_t id; + String name; + NetworkConnection* connection = nullptr; + GameObject* avatar = nullptr; + bool isLocal = false; + bool isReady = false; +}; + +// 网络管理器 +class NetworkManager { +public: + static NetworkManager& Get(); + + void Initialize(const NetworkConfig& config); + void Shutdown(); + + // 模式 + NetworkMode GetMode() const { return m_mode; } + + // 主机 + bool StartHost(uint16_t port); + void StopHost(); + + // 客户端 + bool Connect(const String& address, uint16_t port); + void Disconnect(); + + // 玩家 + uint32_t GetLocalPlayerId() const { return m_localPlayerId; } + NetworkPlayer* GetPlayer(uint32_t id); + const std::vector& GetPlayers(); + + // 消息 + void Send(uint32_t playerId, uint32_t type, const void* data, size_t size, + NetworkChannel channel = NetworkChannel::Reliable); + void SendToAll(uint32_t type, const void* data, size_t size, + NetworkChannel channel = NetworkChannel::Reliable); + + // RPC + template + void RegisterRPC(const String& name, T* obj, void (T::*func)(NetworkReader&)); + + // 场景同步 + void SetNetworkedScene(Scene* scene); + void AddNetworkedObject(GameObject* gameObject); + void RemoveNetworkedObject(GameObject* gameObject); + + // 同步 + void Update(float deltaTime); + + // 事件 + Event OnPlayerConnected; + Event OnPlayerDisconnected; + Event OnMessageReceived; + +private: + NetworkMode m_mode = NetworkMode::Offline; + uint32_t m_localPlayerId = 0; + std::vector m_players; + + void* m_transport = nullptr; // ENet / LiteNetLib / custom +}; + +// 网络组件 +class NetworkIdentityComponent : public Component { +public: + void Update(float deltaTime) override; + + uint32_t networkId = 0; + bool isLocalPlayer = false; + bool isOwnedByClient = false; + bool canSpawn = true; + bool syncTransform = true; + bool syncComponents = true; +}; + +class NetworkTransformComponent : public Component { +public: + void Update(float deltaTime) override; + + enum class SyncMode { + None, + SyncTransform, + SyncPosition, + SyncPositionAndRotation, + SyncPositionRotationScale + }; + + SyncMode syncMode = SyncMode::SyncPositionRotationScale; + float snapThreshold = 0.5f; + float interpolationDelay = 0.1f; + + float syncInterval = 0.05f; + + bool enablePrediction = true; + float predictionTime = 0.1f; + + bool quantizePosition = true; + int positionPrecision = 0.01f; + bool quantizeRotation = true; + int rotationPrecision = 1; +}; + +// 远程过程调用 +namespace RPC { + +// RPC 属性 +enum class RpcTarget { + Server, + Others, + All, + Specific +}; + +enum class RpcMode { + Normal, + Buffered, + Unbuffered +}; + +// RPC 调用 +struct RpcCall { + String methodName; + std::vector args; + RpcTarget target; + uint32_t targetPlayer; + float timestamp; +}; + +// 注册 RPC +#define XE_RPC(methodName, target) \ + void methodName(NetworkReader& reader); \ + static void _RPC_##methodName(NetworkIdentityComponent* identity, NetworkReader& reader) { \ + auto* comp = identity->GetComponent(); \ + if (comp && comp->isOwnedByClient) { \ + auto* obj = static_cast(identity); \ + obj->methodName(reader); \ + } \ + } + +// 服务器/客户端 RPC +class RpcHandler { +public: + void Register(uint32_t hash, std::function handler); + void Call(NetworkIdentityComponent* identity, uint32_t methodHash, NetworkWriter& writer, + RpcTarget target, uint32_t targetPlayer = 0); + void Handle(NetworkMessage& msg); +}; + +} // namespace RPC + +// 网络序列化 +class NetworkSerializer { +public: + void Serialize(NetworkWriter& writer, const GameObject& gameObject); + void Deserialize(NetworkReader& reader, GameObject& gameObject); + + void SerializeTransform(NetworkWriter& writer, const TransformComponent& transform); + void DeserializeTransform(NetworkReader& reader, TransformComponent& transform); + + // 组件同步 + void SerializeComponent(NetworkWriter& writer, uint32_t componentTypeId, const void* component); + void* DeserializeComponent(NetworkReader& reader, uint32_t componentTypeId, GameObject* gameObject); +}; + +// 网络预测 +class ClientPrediction { +public: + struct PredictedState { + Vector3 position; + Quaternion rotation; + Vector3 velocity; + float timestamp; + }; + + void StorePredictedState(const Vector3& position, const Quaternion& rotation, + const Vector3& velocity); + void ApplyServerCorrection(const Vector3& serverPosition, const Quaternion& serverRotation); + + bool HasPredictionError() const; + void Reconcile(); + +private: + std::deque m_predictedStates; + std::deque m_unconfirmedStates; + + Vector3 m_lastServerPosition; + Quaternion m_lastServerRotation; +}; + +// 延迟补偿 +class LagCompensation { +public: + struct ServerFrame { + float timestamp; + std::vector entities; + }; + + void RecordFrame(const std::vector& entities); + EntitySnapshot GetInterpolatedSnapshot(float timestamp); + + bool Raycast(Ray& ray, float maxDistance, RaycastHit& hit); + +private: + std::deque m_frames; + float m_recordDuration = 1.0f; // 记录1秒 +}; + +} // namespace Networking +} // namespace XCEngine +``` + +--- + +## 第十三章 UI 系统 (In-Game UI / UGUI) + +> **架构说明**: Unity UGUI风格的UI系统。UI元素作为组件挂载在GameObject上。 +> 每个UI元素GameObject必须挂载RectTransform组件。 + +### 13.1 UI 系统架构 + +```cpp +namespace XCEngine { +namespace UI { + +// ============================================================================ +// UI 组件 (Unity UGUI风格) +// ============================================================================ + +// 矩形变换组件 (Unity RectTransform,继承 Transform) +class RectTransformComponent : public TransformComponent { +public: + void Update(float deltaTime) override; + + // 锚点 + Vector2 anchorMin = Vector2(0, 0); + Vector2 anchorMax = Vector2(0, 0); + Vector2 pivot = Vector2(0.5f, 0.5f); + + // 位置和大小 + Vector2 anchoredPosition = Vector2::Zero(); + Vector2 sizeDelta = Vector2(100, 100); + + // 偏移 (相对于锚点) + Vector2 offsetMin = Vector2::Zero(); + Vector2 offsetMax = Vector2::Zero(); + + // 计算属性 + Vector3 GetWorldPosition() const; + Vector2 GetWorldSize() const; + void SetSize(const Vector2& size); + +private: + // 父子层级由基类 TransformComponent 管理 + mutable Matrix4x4 m_worldMatrix; + mutable bool m_dirty = true; +}; + +// 图像组件 (Unity Image) +class ImageComponent : public Component { +public: + void Update(float deltaTime) override; + + ResourceGUID spriteGuid; + + enum class Type { + Simple, + Sliced, + Tiled, + Filled + }; + Type type = Type::Simple; + + float fillAmount = 1.0f; + enum class FillMethod { Horizontal, Vertical, Radial90, Radial180, Radial360 }; + FillMethod fillMethod = FillMethod::Horizontal; + bool fillClockwise = true; + int fillOrigin = 0; + + Color color = Color::White; + bool raycastTarget = true; + + Event<> OnSpriteChanged; +}; + +// 文本组件 (Unity Text / TextMeshPro) +class TextComponent : public Component { +public: + void Update(float deltaTime) override; + + String text; + ResourceGUID fontGuid; + + int fontSize = 14; + enum class FontStyle { Normal, Bold, Italic, BoldAndItalic }; + FontStyle fontStyle = FontStyle::Normal; + + Color color = Color::White; + Color outlineColor = Color::Black; + float outlineWidth = 0.0f; + + enum class Alignment { + UpperLeft, UpperCenter, UpperRight, + MiddleLeft, MiddleCenter, MiddleRight, + LowerLeft, LowerCenter, LowerRight + }; + Alignment alignment = Alignment::MiddleCenter; + + float lineSpacing = 1.0f; + bool richText = true; + bool horizontalOverflow = false; + bool verticalOverflow = true; + bool raycastTarget = true; +}; + +// 按钮组件 (Unity Button) +class ButtonComponent : public Component { +public: + void Update(float deltaTime) override; + + enum class Transition { + None, + ColorTint, + SpriteSwap, + Animation + }; + Transition transition = Transition::ColorTint; + + // 颜色状态 + Color normalColor = Color::White; + Color highlightedColor = Color(1, 1, 1, 0.8f); + Color pressedColor = Color(1, 1, 1, 0.6f); + Color disabledColor = Color(1, 1, 1, 0.5f); + + // 精灵状态 + ResourceGUID normalSpriteGuid; + ResourceGUID highlightedSpriteGuid; + ResourceGUID pressedSpriteGuid; + ResourceGUID disabledSpriteGuid; + + // 事件 + Event<> OnClick; + Event<> OnPointerDown; + Event<> OnPointerUp; + Event<> OnPointerEnter; + Event<> OnPointerExit; +}; + +// 输入字段组件 (Unity InputField / TMP_InputField) +class InputFieldComponent : public Component { +public: + void Update(float deltaTime) override; + + String text; + String placeholder; + + int characterLimit = 0; + bool multiLine = false; + bool isPassword = false; + char passwordChar = '*'; + + enum class ContentType { + Standard, + Autocorrected, + DecimalNumber, + IntegerNumber, + Name, + EmailAddress, + Password, + PIN, + MobileTelephoneNumber, + TelephoneNumber, + URL, + Alphabet + }; + ContentType contentType = ContentType::Standard; + + Color color = Color::White; + bool raycastTarget = true; + + // 事件 + Event OnValueChanged; + Event OnEndEdit; + Event<> OnSubmit; +}; + +// 滑动条组件 (Unity Slider) +class SliderComponent : public Component { +public: + void Update(float deltaTime) override; + + float value = 0.5f; + float minValue = 0.0f; + float maxValue = 1.0f; + bool wholeNumbers = false; + + enum class Direction { + LeftToRight, + RightToLeft, + BottomToTop, + TopToBottom + }; + Direction direction = Direction::LeftToRight; + + Color color = Color::White; + bool raycastTarget = true; + + // 事件 + Event OnValueChanged; + Event OnPointerDown; + Event OnPointerUp; +}; + +// 滚动视图组件 (Unity ScrollRect) +class ScrollViewComponent : public Component { +public: + void Update(float deltaTime) override; + + GameObject* contentGameObject = nullptr; + + enum class MovementType { + Elastic, + Clamped, + Unrestricted + }; + MovementType movementType = MovementType::Elastic; + + float elasticity = 0.1f; + float decelerationRate = 0.135f; + + GameObject* horizontalScrollbar = nullptr; + GameObject* verticalScrollbar = nullptr; + + bool enabled = true; + bool raycastTarget = true; +}; + +// 画布组件 (Unity Canvas) +class CanvasComponent : public Component { +public: + void Update(float deltaTime) override; + + enum class RenderMode { + ScreenSpaceOverlay, + ScreenSpaceCamera, + WorldSpace + }; + RenderMode renderMode = RenderMode::ScreenSpaceOverlay; + + GameObject* targetCamera = nullptr; + float planeDistance = 100.0f; + + float scaleFactor = 1.0f; + + int32_t renderOrder = 0; +}; + +// 画布缩放器组件 (Unity CanvasScaler) +class CanvasScalerComponent : public Component { +public: + void Update(float deltaTime) override; + + enum class ScaleMode { + ConstantPixelSize, + ScaleWithScreenSize, + ConstantPhysicalSize + }; + ScaleMode uiScaleMode = ScaleMode::ScaleWithScreenSize; + + Vector2 referenceResolution = Vector2(800, 600); + float referencePixelsPerUnit = 100.0f; + + enum class ScreenMatchMode { + Width, + Height, + Expand, + Shrink + }; + ScreenMatchMode screenMatchMode = ScreenMatchMode::Expand; + + float matchWidthOrHeight = 0.0f; +}; + +// 布局元素组件 (用于布局组) +class LayoutElementComponent : public Component { +public: + void Update(float deltaTime) override; + + float minWidth = 0.0f; + float minHeight = 0.0f; + float preferredWidth = 0.0f; + float preferredHeight = 0.0f; + float flexibleWidth = 0.0f; + float flexibleHeight = 0.0f; + int32_t layoutPriority = 0; +}; + +// 水平布局组组件 (Unity HorizontalLayoutGroupComponent) +class HorizontalLayoutGroupComponent : public Component { +public: + void Update(float deltaTime) override; + + float spacing = 0.0f; + bool childForceExpandWidth = true; + bool childForceExpandHeight = false; + bool childControlWidth = true; + bool childControlHeight = true; + int32_t childAlignment = 4; +}; + +// 垂直布局组组件 (Unity VerticalLayoutGroupComponent) +class VerticalLayoutGroupComponent : public Component { +public: + void Update(float deltaTime) override; + + float spacing = 0.0f; + bool childForceExpandWidth = false; + bool childForceExpandHeight = true; + bool childControlWidth = true; + bool childControlHeight = true; + int32_t childAlignment = 4; +}; + +// 网格布局组组件 (Unity GridLayoutGroupComponent) +class GridLayoutGroupComponent : public Component { +public: + void Update(float deltaTime) override; + + Vector2 cellSize = Vector2(100, 100); + Vector2 spacing = Vector2::Zero(); + int32_t startCorner = 0; + int32_t startAxis = 0; + int32_t constraint = 0; + int32_t constraintCount = 2; +}; + +// ============================================================================ +// UI 系统 (处理布局、事件等 - 传统Unity风格) +// ============================================================================ + +class UISystem { +public: + void Initialize(); + void Shutdown(); + void Update(float deltaTime); + + // 射线检测 + GameObject* Raycast(const Vector2& screenPosition); + std::vector RaycastAll(const Vector2& screenPosition); + + // 焦点管理 + void SetFocus(GameObject* element); + GameObject* GetFocusedElement(); + void ClearFocus(); + +private: + void ProcessLayoutGroups(); + void ProcessRaycasts(); + void ProcessEvents(); + + GameObject* m_focusedElement = nullptr; + GameObject* m_hoveredElement = nullptr; +}; + +// ============================================================================ +// UI 渲染器 (底层实现) +// ============================================================================ + +class UIRenderer { +public: + void Initialize(); + void Shutdown(); + + void Render(Scene& scene); + + // 批处理 + void BeginBatch(); + void AddToBatch(GameObject* gameObject, const Matrix4x4& transform, const Mesh* mesh, const Material* material); + void EndBatch(); + + // 默认材质 + Material* defaultMaterial = nullptr; + Material* defaultSpriteMaterial = nullptr; +}; + +// ============================================================================ +// 画布渲染器组件 (挂载在 Canvas 上) +class CanvasRendererComponent : public Component { +public: + void Update(float deltaTime) override; + + bool renderMode = true; + uint32_t vertexCount = 0; + uint32_t indexCount = 0; + bool hasPopulateMesh = false; + + std::function onPopulateMesh; +}; + +// ============================================================================ +// UI 事件系统 +// ============================================================================ + +class UIEventSystem { +public: + static UIEventSystem& Get(); + + // 指针事件 + void OnPointerDown(PointerEvent& event); + void OnPointerUp(PointerEvent& event); + void OnPointerMove(PointerEvent& event); + void OnPointerClick(PointerEvent& event); + + // 键盘事件 + void OnKeyDown(KeyEvent& event); + void OnKeyUp(KeyEvent& event); + void OnTextInput(TextInputEvent& event); + + // 拖放事件 + void OnDragStart(DragEvent& event); + void OnDrag(DragEvent& event); + void OnDragEnd(DragEvent& event); + +private: + GameObject* m_currentPointerOver = nullptr; + GameObject* m_draggedElement = nullptr; + GameObject* m_focusedElement = nullptr; +}; + +} // namespace UI +} // namespace XCEngine +``` + +--- + +## 第十四章 编辑器架构 (Editor) + +### 14.1 编辑器整体架构 + +```cpp +namespace XCEngine { +namespace Editor { + +// 编辑器应用 +class EditorApplication { +public: + static EditorApplication& Get(); + + void Initialize(); + void Shutdown(); + void Run(); + + // 主循环 + void Update(); + void Render(); + + // 项目 + Project* GetCurrentProject() { return m_currentProject.get(); } + void NewProject(const String& path); + void OpenProject(const String& path); + void SaveProject(); + void CloseProject(); + + // 编辑器状态 + enum class Mode { + Stopped, + Playing, + Paused, + Step + }; + Mode GetMode() const { return m_mode; } + void Play(); + void Pause(); + void Stop(); + void Step(); + + // 场景操作 + void NewScene(); + void OpenScene(const String& path); + void SaveScene(); + void SaveSceneAs(const String& path); + + // 窗口 + void RegisterWindow(EditorWindow* window); + void UnregisterWindow(EditorWindow* window); + +private: + std::unique_ptr m_currentProject; + Mode m_mode = Mode::Stopped; + std::vector> m_windows; +}; + +// 编辑器窗口基类 +class EditorWindow { +public: + virtual ~EditorWindow() = default; + + virtual void OnOpen() {} + virtual void OnClose() {} + virtual void Update(float deltaTime) {} + virtual void OnGUI() {} + + virtual bool IsOpen() const { return m_open; } + void SetOpen(bool open) { m_open = open; } + + virtual ImVec2 GetSize() const { return ImVec2(400, 300); } + virtual ImVec2 GetPosition() const { return ImVec2(0, 0); } + +protected: + String m_title; + bool m_open = true; +}; + +// 项目 +class Project { +public: + String name; + String path; + String assemblyName; + + // 设置 + ProjectSettings settings; + + // 资源(使用编辑器专用的资源数据库) + EditorAssetDatabase* GetAssetDatabase() { return m_assetDatabase.get(); } + + // 场景 + std::vector GetScenes(); + void AddScene(const String& scenePath); + void RemoveScene(const String& scenePath); + + // 构建 + void Build(const BuildSettings& settings); + +private: + std::unique_ptr m_assetDatabase; + std::vector m_scenes; +}; + +// 编辑器资源数据库(继承自 Resources::AssetDatabase) +class EditorAssetDatabase { +public: + void Initialize(const String& projectPath); + void Shutdown(); + + // 资源查找 + Resources::ResourceGUID FindAsset(const String& guid) const; + Resources::ResourceGUID FindAssetByPath(const String& path) const; + String GetAssetPath(const Resources::ResourceGUID& guid) const; + + // 资源操作 + void ImportAsset(const String& sourcePath); + void ReimportAsset(const Resources::ResourceGUID& guid); + void DeleteAsset(const Resources::ResourceGUID& guid); + + // 刷新 + void Refresh(); + + // GUID 生成 + Resources::ResourceGUID GenerateGUID(); + + // 编辑器特定功能 + void SelectAsset(const Resources::ResourceGUID& guid); + std::vector GetSelectedAssets() const; + void OpenInExternalEditor(const Resources::ResourceGUID& guid); + + // 资源变换监听 + Core::Event OnAssetRenamed; + Core::Event OnAssetDeleted; + +private: + void ScanDirectory(const String& dirPath); + void ImportAssetInternal(const String& sourcePath, const String& destPath); + + struct AssetMetadata { + Resources::ResourceGUID guid; + String path; + String extension; + int64_t fileSize; + int64_t lastModified; + String importerType; + JsonObject metadata; + }; + + std::unordered_map m_guidToAsset; + std::unordered_map m_pathToGuid; + + std::vector m_selectedAssets; +}; + +// 资源导入器 +class AssetImporter { +public: + virtual ~AssetImporter() = default; + + virtual bool CanImport(const String& extension) const = 0; + virtual void Import(const String& sourcePath, const ResourceGUID& guid, + const ImportSettings& settings) = 0; + virtual ImportSettings* GetDefaultSettings() const = 0; + +protected: + String GetOutputPath(const String& sourcePath, const ResourceGUID& guid); +}; + +// 具体导入器 +class TextureImporter : public AssetImporter { +public: + bool CanImport(const String& extension) const override; + void Import(const String& sourcePath, const ResourceGUID& guid, + const ImportSettings& settings) override; + + struct Settings : ImportSettings { + TextureType textureType = TextureType::Texture2D; + int maxSize = 2048; + TextureFormat format = TextureFormat::RGBA; + bool generateMipmaps = true; + bool sRGB = true; + FilterMode filterMode = FilterMode::Bilinear; + WrapMode wrapMode = WrapMode::Repeat; + }; +}; + +class MeshImporter : public AssetImporter { +public: + bool CanImport(const String& extension) const override; + void Import(const String& sourcePath, const ResourceGUID& guid, + const ImportSettings& settings) override; +}; + +class MaterialImporter : public AssetImporter { +public: + bool CanImport(const String& extension) const override; + void Import(const String& sourcePath, const ResourceGUID& guid, + const ImportSettings& settings) override; +}; + +// 编辑器场景管理 (Unity Editor 风格) +// +// 编辑器/运行时模式切换机制: +// - Stop (编辑模式): 编辑器直接操作 m_editingScene +// - Play (运行模式): +// 1. 深拷贝 m_editingScene -> m_runtimeScene (包括所有Entity和Component) +// 2. 运行 m_runtimeScene +// 3. 用户在运行时对Scene的修改都在 m_runtimeScene 中 +// - Stop -> Play 循环: +// 1. 销毁旧的 m_runtimeScene (如果存在) +// 2. 深拷贝 m_editingScene -> m_runtimeScene +// - Play -> Stop: +// 1. 销毁 m_runtimeScene +// 2. 如果用户选择了 "Apply Changes",将 runtime 改动的 GameObject 同步回 editing +// 3. 恢复编辑模式 +class EditorSceneManager { +public: + static EditorSceneManager& Get(); + + // 编辑场景 (编辑模式下使用) + Scene* GetEditingScene() { return m_editingScene.get(); } + + // 运行时场景 (Play 模式下使用) + // 注意:运行时场景是编辑场景的副本,不是同一个对象 + Scene* GetRuntimeScene() { return m_runtimeScene.get(); } + + // Play/Stop 控制 + enum class Mode { + Stopped, // 编辑模式 + Playing, // 播放模式 + Paused // 暂停模式 + }; + + void Play(); // 开始播放:从 editing 拷贝到 runtime + void Pause(); // 暂停 + void Unpause(); // 继续 + void Stop(); // 停止播放:销毁 runtime,可选 Apply Changes + void Step(); // 单步执行一帧 + + Mode GetMode() const { return m_mode; } + + // Apply Changes (Play -> Stop 时可选) + // 将 runtime 场景中的运行时数据同步回 editing 场景 + enum class ApplyChangesMode { + None, // 不应用任何更改 + All, // 应用所有更改 + Selected // 只应用选中的GameObject + }; + void SetApplyChangesMode(ApplyChangesMode mode); + void ApplyRuntimeChanges(); + + // 场景操作 + void CreateNewScene(); + void OpenScene(const String& path); + void SaveScene(const String& path); + + // 撤销/重做 + void Undo(); + void Redo(); + bool CanUndo() const; + bool CanRedo() const; + + // GameObject操作 + void DuplicateGameObject(GameObject* gameObject); + void DeleteGameObject(GameObject* gameObject); + void PasteGameObject(); + void CopyGameObject(GameObject* gameObject); + + // 预制件 + void CreatePrefab(GameObject* gameObject, const String& path); + GameObject* InstantiatePrefab(const String& path); + void UnpackPrefab(GameObject* gameObject); + +private: + void CopySceneToRuntime(); // 深拷贝编辑场景到运行时场景 + void SyncRuntimeToEditing(); // 同步运行时更改回编辑场景 + + std::unique_ptr m_editingScene; + std::unique_ptr m_runtimeScene; + + Mode m_mode = Mode::Stopped; + ApplyChangesMode m_applyChangesMode = ApplyChangesMode::None; + + std::deque m_undoStack; + std::deque m_redoStack; +}; + +// 撤销/重做 +class UndoRedoSystem { +public: + void PushAction(std::unique_ptr action); + void Undo(); + void Redo(); + + bool CanUndo() const { return !m_undoStack.empty(); } + bool CanRedo() const { return !m_redoStack.empty(); } + + void Clear(); + +private: + std::deque> m_undoStack; + std::deque> m_redoStack; + size_t m_maxStackSize = 100; +}; + +// 编辑器工具 +namespace Tools { + +class EditorTool { +public: + virtual ~EditorTool() = default; + virtual void OnActivate() {} + virtual void OnDeactivate() {} + virtual void Update(float deltaTime) {} + virtual void OnSceneGUI() {} + virtual void OnObjectGUI(GameObject* gameObject) {} + + virtual const char* GetName() const = 0; + virtual const char* GetIcon() const = 0; + +protected: + bool m_active = false; +}; + +class SelectionTool : public EditorTool { +public: + const char* GetName() const override { return "Select"; } + void Update(float deltaTime) override; + void OnSceneGUI() override; +}; + +class MoveTool : public EditorTool { +public: + const char* GetName() const override { return "Move"; } + void Update(float deltaTime) override; + void OnSceneGUI() override; +}; + +class RotateTool : public EditorTool { +public: + const char* GetName() const override { return "Rotate"; } + void Update(float deltaTime) override; + void OnSceneGUI() override; +}; + +class ScaleTool : public EditorTool { +public: + const char* GetName() const override { return "Scale"; } + void Update(float deltaTime) override; + void OnSceneGUI() override; +}; + +class Gizmo { +public: + enum class Mode { + Translate, + Rotate, + Scale, + Rect, + Transform + }; + + enum class Space { + World, + Local + }; + + enum class PivotMode { + Center, + Pivot + }; + + void SetMode(Mode mode); + void SetSpace(Space space); + void SetPivot(PivotMode pivot); + + void BeginManipulation(GameObject* gameObject); + void Draw(GameObject* gameObject); + void EndManipulation(); + + bool IsManipulating() const { return m_manipulating; } + Matrix4x4 GetManipulationDelta() const; + +private: + Mode m_mode = Mode::Translate; + Space m_space = Space::World; + PivotMode m_pivot = PivotMode::Center; + bool m_manipulating = false; + GameObject* m_selectedGameObject = nullptr; + Matrix4x4 m_startMatrix; +}; + +// 编辑器相机 +class EditorCamera { +public: + void Initialize(); + void Shutdown(); + + void Update(float deltaTime); + + void SetProjection(float fov, float aspect, float near, float far); + void SetOrthographic(float size, float near, float far); + + Matrix4x4 GetViewMatrix() const; + Matrix4x4 GetProjectionMatrix() const; + + // 控制 + void Orbit(const Vector2& delta); + void Pan(const Vector2& delta); + void Zoom(float delta); + + void FocusOn(GameObject* gameObject); + void FocusOn(const BoundingBox& bounds); + + // 状态 + float GetDistance() const { return m_distance; } + void SetDistance(float distance); + + Vector3 GetPosition() const; + Vector3 GetForward() const; + Vector3 GetTarget() const { return m_target; } + +private: + Vector3 m_target = Vector3::Zero(); + float m_distance = 10.0f; + float m_pitch = 0.0f; + float m_yaw = 0.0f; + + float m_fov = 60.0f; + float m_near = 0.1f; + float m_far = 1000.0f; + bool m_orthographic = false; + + // 交互 + bool m_isOrbiting = false; + bool m_isPanning = false; +}; + +} // namespace Tools + +// 编辑器面板 +namespace Panels { + +class HierarchyPanel { +public: + void OnGUI(); + + void SetSearchFilter(const String& filter); + void DrawGameObjectTree(GameObject* parent, int& idCounter); + +private: + String m_searchFilter; + GameObject* m_contextMenuGameObject = nullptr; +}; + +class InspectorPanel { +public: + void OnGUI(); + + void DrawGameObject(GameObject* gameObject); + void DrawComponent(uint32_t componentTypeId, void* component); + void DrawAddComponentMenu(); + +private: + GameObject* m_selectedGameObject = nullptr; +}; + +class SceneViewPanel { +public: + void OnGUI(); + void Render(); + + Tools::EditorCamera& GetCamera() { return m_camera; } + +private: + Tools::EditorCamera m_camera; + bool m_gridVisible = true; + bool m_gizmosVisible = true; +}; + +class GameViewPanel { +public: + void OnGUI(); + void Render(); + + void SetResolution(int width, int height); + void SetFullscreen(bool fullscreen); + +private: + int m_width = 1280; + int m_height = 720; + bool m_fullscreen = false; + bool m_vsync = true; +}; + +class ProjectPanel { +public: + void OnGUI(); + + void DrawAssetBrowser(); + void DrawFolderTree(); + + void OnAssetSelected(ResourceGUID guid); + +private: + String m_currentPath; + std::vector m_selectedAssets; + ViewMode m_viewMode = ViewMode::Grid; +}; + +class ConsolePanel { +public: + void OnGUI(); + + void Log(const String& message, LogLevel level); + void Clear(); + void Filter(LogLevel minLevel); + +private: + struct LogEntry { + String message; + LogLevel level; + String source; + int64_t timestamp; + }; + + std::vector m_logs; + LogLevel m_filterLevel = LogLevel::Info; +}; + +// 动画曲线编辑器 +class AnimationCurveEditor { +public: + void OnGUI(); + + void SetCurve(AnimationCurve* curve); + void AddKey(float time, float value); + void RemoveKey(int index); + +private: + AnimationCurve* m_curve = nullptr; + int m_selectedKey = -1; +}; + +// 着色器编辑器 +class ShaderEditor { +public: + void OnGUI(); + + void OpenShader(const String& path); + void SaveShader(); + void CompileShader(); + + void SetPreviewMesh(Mesh* mesh); + void SetPreviewRotation(const Vector3& rotation); + +private: + String m_shaderPath; + bool m_compileErrors = false; + String m_errorMessage; +}; + +// 材质编辑器 +class MaterialEditor { +public: + void OnGUI(); + + void OpenMaterial(Material* material); + void SaveMaterial(); + + void DrawProperty(MaterialProperty* property); + +private: + Material* m_material = nullptr; +}; + +// 偏好设置 +class PreferencesWindow : public EditorWindow { +public: + void OnGUI() override; + +private: + void DrawGeneralSettings(); + void DrawThemeSettings(); + void DrawInputSettings(); + void DrawShortcutSettings(); +}; + +} // namespace Panels + +// 编辑器渲染 +class EditorRenderView { +public: + void Initialize(); + void Shutdown(); + + void RenderSceneView(Panels::SceneViewPanel* panel); + void RenderGameView(Panels::GameViewPanel* panel); + + void SetRenderTarget(RenderTexture* target); + +private: + void SetupCamera(EditorCamera& camera); + void RenderGizmos(); + + RenderTexture* m_renderTarget = nullptr; +}; + +} // namespace Editor +} // namespace XCEngine +``` + +--- + +## 第十五章 工具链 (Toolchain) + +### 15.1 资源处理管道 + +```cpp +namespace XCEngine { +namespace Tools { + +// 资源处理器 +class AssetProcessor { +public: + static AssetProcessor& Get(); + + void Initialize(const String& projectPath); + void Shutdown(); + + // 导入 + void ImportAsset(const String& sourcePath); + void ImportAllAssets(); + + // 烘焙 + void CookScene(Scene* scene, const String& outputPath); + void CookMaterial(Material* material, const String& outputPath); + void CookTexture(Texture* texture, const String& outputPath); + + // 构建 + void BuildProject(const BuildSettings& settings); + +private: + void ProcessImportQueue(); + void WriteCookedData(const String& path, const void* data, size_t size); + + std::queue m_importQueue; +}; + +// 着色器编译器 +class ShaderCompiler { +public: + void Initialize(); + void Shutdown(); + + // 编译 + CompiledShader Compile(const ShaderSource& source, const ShaderCompileOptions& options); + bool CompileFile(const String& inputPath, const String& outputPath, + const ShaderCompileOptions& options); + + // 工具 + void GenerateShaderIncludes(); + void StripDebugInfo(CompiledShader& shader); + + // 工具链 + enum class ShaderProfile { + DXIL, // DirectX 12 + SPIRV, // Vulkan + MSL, // Metal + GLSL, // OpenGL + WGSL // WebGPU + }; + + void SetProfile(ShaderProfile profile); + void AddPreprocessorDefine(const String& define); + +private: + struct CompilerConfig { + ShaderProfile profile; + std::vector defines; + bool generateDebugInfo = false; + bool optimize = true; + int optimizationLevel = 3; + }; + + CompilerConfig m_config; +}; + +// 场景烘焙器 +class SceneCooker { +public: + void Cook(Scene* scene, const CookSettings& settings); + + // 灯光烘焙 + void BakeLightmaps(Scene* scene); + void BakeReflectionProbes(Scene* scene); + void BakeAmbientOcclusion(Scene* scene); + + // 导航烘焙 + void BakeNavigationMesh(Scene* scene); + + // 遮挡剔除 + void BakeOcclusionCulling(Scene* scene); + + // 静态批处理 + void BakeStaticBatches(Scene* scene); + +private: + void CookGameObject(GameObject* gameObject); + void WriteCookedScene(const String& path, const CookedScene& data); +}; + +// 构建工具 +class BuildTool { +public: + struct BuildSettings { + String outputPath; + String projectName; + + // 平台 + BuildPlatform platform; + BuildConfiguration config = BuildConfiguration::Release; + + // 脚本 + bool compileScripts = true; + bool generateDebugSymbols = false; + + // 资源 + bool compressAssets = true; + bool stripUnusedResources = true; + + // 目标 + bool buildExe = true; + bool buildDLC = false; + bool bundleResources = true; + }; + + void Build(const BuildSettings& settings); + void BuildPlayer(const BuildSettings& settings); + void BuildAssetBundle(const BuildSettings& settings); + +private: + void PrepareBuildDirectory(const BuildSettings& settings); + void CompileScripts(const BuildSettings& settings); + void CookResources(const BuildSettings& settings); + void CopyEngineFiles(const BuildSettings& settings); + void LinkExecutable(const BuildSettings& settings); +}; + +// 性能分析器工具 +class ProfilerCapture { +public: + void StartCapture(); + void StopCapture(); + + void SaveCapture(const String& path); + void LoadCapture(const String& path); + + // 分析 + void GenerateReport(); + float GetTotalFrameTime() const; + float GetCPUFrameTime() const; + float GetGPUFrameTime() const; + +private: + struct FrameData { + uint64_t timestamp; + std::vector events; + }; + + std::vector m_frames; + bool m_capturing = false; +}; + +} // namespace Tools +} // namespace XCEngine +``` + +--- + +## 第十六章 平台层 (Platform) + +### 16.1 跨平台抽象 + +```cpp +namespace XCEngine { +namespace Platform { + +// 平台类型 +enum class PlatformType { + Windows, + Linux, + macOS, + Android, + iOS, + Web, + PlayStation, + Xbox, + Nintendo +}; + +// 键码 +enum class KeyCode { + None = 0, + A = 4, B = 5, C = 6, D = 7, E = 8, F = 9, G = 10, + H = 11, I = 12, J = 13, K = 14, L = 15, M = 16, N = 17, + O = 18, P = 19, Q = 20, R = 21, S = 22, T = 23, U = 24, + V = 25, W = 26, X = 27, Y = 28, Z = 29, + F1 = 122, F2 = 120, F3 = 99, F4 = 118, F5 = 96, F6 = 97, + F7 = 98, F8 = 100, F9 = 101, F10 = 109, F11 = 103, F12 = 111, + Space = 49, Tab = 48, Enter = 36, Escape = 53, + LeftShift = 56, RightShift = 60, LeftCtrl = 59, RightCtrl = 62, + LeftAlt = 58, RightAlt = 61, + Up = 126, Down = 125, Left = 123, Right = 124, + Home = 115, End = 119, PageUp = 116, PageDown = 121, + Delete = 51, Backspace = 51 +}; + +// 鼠标按钮 +enum class MouseButton { + Left = 0, + Right = 1, + Middle = 2, + Button4 = 3, + Button5 = 4 +}; + +// 触摸状态 +struct TouchState { + int touchId; + Vector2 position; + Vector2 deltaPosition; + float deltaTime; + int tapCount; + enum Phase { Began, Moved, Stationary, Ended, Canceled } phase; +}; + +// 指针事件 +struct PointerEvent { + int pointerId; + Vector2 position; + Vector2 deltaPosition; + float pressure; + MouseButton button; + enum Type { Pressed, Released, Moved, Wheel, Hover } type; +}; + +// 按键事件 +struct KeyEvent { + KeyCode keyCode; + bool alt; + bool ctrl; + bool shift; + bool meta; + enum Type { Down, Up, Repeat } type; +}; + +// 文本输入事件 +struct TextInputEvent { + char character; + String text; +}; + +// 拖放事件 +struct DragEvent { + Vector2 position; + Vector2 delta; + int pointerId; +}; + +// 文件变化事件 +struct FileChangeEvent { + String path; + enum Type { Created, Modified, Deleted, Renamed } type; +}; + +// 手势事件 +struct GestureEvent { + Vector2 position; + float deltaScale; + float deltaRotation; + int tapCount; + enum Type { None, Tap, DoubleTap, Pinch, Rotate, Pan } type; +}; + +// 窗口 +class Window { +public: + virtual ~Window() = default; + + virtual void Create(const WindowDesc& desc) = 0; + virtual void Destroy() = 0; + + virtual void Show() = 0; + virtual void Hide() = 0; + virtual void Minimize() = 0; + virtual void Maximize() = 0; + virtual void Restore() = 0; + virtual void SetFullscreen(bool fullscreen) = 0; + + virtual void SetTitle(const String& title) = 0; + virtual void SetSize(int width, int height) = 0; + virtual void SetPosition(int x, int y) = 0; + + virtual bool IsClosed() const = 0; + virtual bool IsFocused() const = 0; + virtual bool IsMinimized() const = 0; + virtual bool IsMaximized() const = 0; + virtual bool IsFullscreen() const = 0; + + virtual void* GetNativeHandle() const = 0; + + // 事件 + Event OnResize; + Event OnMove; + Event<> OnClose; + Event<> OnFocus; + Event<> OnBlur; + Event<> OnMinimize; + Event<> OnMaximize; + Event<> OnRestore; +}; + +// 输入 +class InputSystem { +public: + // 键盘 + bool IsKeyDown(KeyCode key) const; + bool IsKeyUp(KeyCode key) const; + bool IsKeyPressed(KeyCode key) const; + + // 鼠标 + Vector2 GetMousePosition() const; + Vector2 GetMouseDelta() const; + float GetMouseScrollDelta() const; + bool IsMouseButtonDown(MouseButton button) const; + bool IsMouseButtonUp(MouseButton button) const; + bool IsMouseButtonClicked(MouseButton button) const; + + // 手柄 + int GetJoystickCount() const; + bool IsJoystickConnected(int joystick) const; + Vector2 GetJoystickAxis(int joystick, int axis) const; + bool IsJoystickButtonDown(int joystick, int button) const; + + // 触摸 + int GetTouchCount() const; + TouchState GetTouch(int index) const; + + // 手势 + Event OnGesture; +}; + +// 注意:FileSystem 定义在 Platform 命名空间中 +// Core::IO 只保留流抽象 (IStream, FileReader, FileWriter) +} + +namespace XCEngine { +namespace Platform { + +// 文件系统 - 统一的跨平台文件系统抽象 +class FileSystem { +public: + static FileSystem& Get(); + + // 路径操作 + String GetWorkingDirectory(); + String GetExecutablePath(); + String GetUserDirectory(); + String GetAppDataDirectory(); + String GetTempDirectory(); + + // 文件操作 + bool FileExists(const String& path); + bool DirectoryExists(const String& path); + bool CreateDirectory(const String& path); + bool DeleteFile(const String& path); + bool DeleteDirectory(const String& path); + + // 读写 + std::unique_ptr OpenRead(const String& path); + std::unique_ptr OpenWrite(const String& path); + std::unique_ptr OpenAppend(const String& path); + + // 遍历 + void EnumerateFiles(const String& directory, const String& pattern, + std::vector& results); + void EnumerateDirectories(const String& directory, + std::vector& results); + + // 观察 + void WatchDirectory(const String& directory, + std::function callback); +}; + +// 时间 + +// 时间 +class Time { +public: + static float GetTime(); + static float GetUnscaledTime(); + static float GetDeltaTime(); + static float GetUnscaledDeltaTime(); + + static void SetTimeScale(float scale); + static float GetTimeScale() { return m_timeScale; } + + static uint64_t GetFrameCount() { return m_frameCount; } + static int GetFrameRate() { return m_frameRate; } + + static void SetTargetFrameRate(int rate); + static void BeginFrame(); + static void EndFrame(); + +private: + static float m_timeScale; + static uint64_t m_frameCount; + static int m_frameRate; +}; + +// 内存映射文件 +class MemoryMappedFile { +public: + bool Open(const String& path); + void Close(); + + void* GetData() const { return m_data; } + size_t GetSize() const { return m_size; } + +private: + void* m_handle = nullptr; + void* m_data = nullptr; + size_t m_size = 0; +}; + +// 进程 +class Process { +public: + bool Launch(const String& command, const std::vector& args); + void Terminate(); + bool IsRunning() const; + + int GetExitCode() const; + int WaitForExit(); + + void Write(const void* data, size_t size); + String ReadOutput(); + String ReadError(); + +private: + void* m_handle = nullptr; +}; + +// 动态库 +class DynamicLibrary { +public: + bool Load(const String& path); + void Unload(); + + void* GetFunction(const String& name); + bool IsLoaded() const; + +private: + void* m_handle = nullptr; +}; + +// 系统信息 +class SystemInfo { +public: + static String GetOSName(); + static String GetOSVersion(); + static String GetMachineName(); + static String GetUserName(); + + static int GetProcessorCount(); + static int GetProcessorCoreCount(); + static int GetThreadCount(); + + static uint64_t GetTotalMemory(); + static uint64_t GetAvailableMemory(); + + static String GetGPUName(); + static uint64_t GetGPUMemory(); + static int GetGPUMonitorCount(); + + static bool HasNvidiaGPU(); + static bool HasAmdGPU(); + static bool HasIntelGPU(); +}; + +} // namespace Platform +} // namespace XCEngine +``` + +--- + +## 第十七章 构建与部署 + +### 17.1 CMake 项目结构 + +``` +XCVolumeRenderer/ +├── CMakeLists.txt # 根 CMake 配置 +├── cmake/ +│ ├── FindXXX.cmake # 第三方库查找 +│ ├── XCEngineDefaults.cmake # 默认设置 +│ └── Utils.cmake # 工具宏 +│ +├── engine/ # 引擎核心 +│ ├── CMakeLists.txt +│ ├── include/ +│ └── src/ +│ +├── editor/ # 编辑器 +│ ├── CMakeLists.txt +│ └── src/ +│ +├── runtime/ # 运行时 +│ ├── CMakeLists.txt +│ └── src/ +│ +├── tools/ # 工具链 +│ ├── AssetProcessor/ +│ ├── ShaderCompiler/ +│ └── SceneCooker/ +│ +└── third_party/ # 第三方库 + ├── CMakeLists.txt + ├── imgui/ + ├── stb/ + └── ... +``` + +### 17.2 CMake 配置示例 + +```cmake +# 根 CMakeLists.txt +cmake_minimum_required(VERSION 3.20) +project(XCGameEngine VERSION 1.0.0) + +# 选项 +option(BUILD_EDITOR "Build editor" ON) +option(BUILD_RUNTIME "Build runtime" ON) +option(BUILD_TOOLS "Build tools" ON) +option(BUILD_SHADERS "Build shaders" ON) + +# 加载工具 +list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +include(XCEngineDefaults) + +# 依赖 +find_package(Threads REQUIRED) +find_package(D3D12 REQUIRED) +find_package(Vulkan REQUIRED) + +# 子目录 +add_subdirectory(third_party) +add_subdirectory(engine) + +if(BUILD_EDITOR) + add_subdirectory(editor) +endif() + +if(BUILD_RUNTIME) + add_subdirectory(runtime) +endif() + +if(BUILD_TOOLS) + add_subdirectory(tools) +endif() +``` + +### 17.3 构建流程 + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Build Pipeline │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ Source Code ──► Compile ──► Link ──► Engine Library │ +│ │ │ +│ │ │ +│ ▼ │ +│ Assets ──► Import ──► Cook ──► Pack ──► Resource Bundle │ +│ │ +│ │ │ +│ │ │ +│ ▼ │ +│ Shaders ──► Compile ──► Pack ──► Shader Cache │ +│ │ +│ │ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ Final Output │ │ +│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │ │ +│ │ │ Executable │ │ Resources │ │ Engine Libraries │ │ │ +│ │ │ (EXE/DLL) │ │ (.pak) │ │ (.lib/.dll) │ │ │ +│ │ └──────────────┘ └──────────────┘ └──────────────────────────┘ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 第十八章 总结与实现建议 + +### 18.1 架构核心要点 + +1. **分层设计**: Platform → Core → Engine → Editor/Runtime +2. **组件系统**: 类Unity的GameObject+Component模式 +3. **渲染抽象**: 跨 API 的渲染接口,便于扩展 +4. **资源管理**: 完整的导入→处理→缓存→加载管道 +5. **工具链**: 从源代码到最终产品的完整构建系统 + +### 18.2 实现优先级建议 + +#### 第一阶段 (基础框架) +- [ ] 数学库 (Vector, Matrix, Quaternion, Transform) +- [ ] 基础容器 (Array, String, HashMap) +- [ ] 内存管理 (Allocator, Pool) +- [ ] 线程系统 (Thread, Mutex, TaskSystem) +- [ ] 日志系统 +- [ ] 文件系统抽象 + +#### 第二阶段 (组件系统 + 渲染) +- [ ] 组件系统核心 (GameObject, Component) +- [ ] 基础组件 (Transform, RenderMesh) +- [ ] 渲染抽象层 (Device, CommandList) +- [ ] D3D12/Vulkan 后端 +- [ ] 基础渲染管线 (GBuffer, Lighting) + +#### 第三阶段 (功能系统) +- [ ] 资源系统 (ResourceManager, AssetDatabase) +- [ ] 场景系统 (Scene, SceneManager) +- [ ] 物理系统 (基础碰撞检测) +- [ ] 输入系统 +- [ ] UI 框架 + +#### 第四阶段 (编辑器) +- [ ] 编辑器 UI (ImGui) +- [ ] 场景视图/游戏视图 +- [ ] 层级面板/检视面板 +- [ ] 资源浏览器 +- [ ] 工具 (Gizmo, 编辑器相机) + +#### 第五阶段 (高级功能) +- [ ] 动画系统 +- [ ] 粒子系统 +- [ ] 音频系统 +- [ ] 网络系统 +- [ ] 脚本系统 + +### 18.3 代码组织建议 + +``` +engine/src/ +├── Core/ # 1-2周 +│ ├── Math/ +│ ├── Containers/ +│ ├── Memory/ +│ ├── Threading/ +│ └── Debug/ +├── Components/ # 2-3周 +│ ├── GameObject.cpp +│ ├── Component.cpp +│ └── System.cpp +├── Renderer/ # 3-4周 +│ ├── Device.cpp +│ ├── CommandList.cpp +│ ├── Pipeline.cpp +│ └── Passes/ +├── Resources/ # 2周 +│ ├── ResourceManager.cpp +│ ├── AssetDatabase.cpp +│ └── Loaders/ +├── Scene/ # 1周 +├── Physics/ # 2-3周 +├── Scripting/ # 3-4周 (可选) +└── Platform/ # 1周 + ├── Windows.cpp + └── ... + +editor/src/ +├── Application.cpp # 1周 +├── Panels/ # 2周 +├── Tools/ # 2周 +├── Windows/ # 2周 +└── ImGui/ # 1周 +``` + +### 18.4 技术选型建议 + +| 子系统 | 推荐方案 | 备选 | +|--------|----------|------| +| 图形 API | D3D12 + Vulkan | Metal, OpenGL | +| 物理 | PhysX | Bullet, Box2D | +| 脚本 | C# (Mono/.NET) | Lua, AngelScript | +| UI (编辑器) | ImGui | Qt, Custom | +| UI (运行时) | 自研 Canvas | DearImgui, RmlUI | +| 资源格式 | 自研 Binary + JSON | glTF, USD | +| 压缩 | LZ4 + ZSTD | LZMA, LZHAM | +| 网络 | 自研 / ENet | LiteNetLib | + +### 18.5 性能目标 + +- 60 FPS 稳定运行 (1080p, 中等画质) +- 10000+ 实体同屏 +- 加载时间 < 3秒 (典型场景) +- 编辑器响应 < 16ms + +--- + +*文档版本: 1.15* +*最后更新: 2026-03-13* diff --git a/docs/plan/仿Unity RHI架构设计.md b/docs/plan/仿Unity RHI架构设计.md new file mode 100644 index 0000000..7f0c79e --- /dev/null +++ b/docs/plan/仿Unity RHI架构设计.md @@ -0,0 +1,1325 @@ +# Unity风格RHI架构设计方案 + +## 一、概述 + +### 1.1 设计目标 + +本设计方案参考Unity引擎的渲染架构,设计一套跨平台的渲染抽象层(Graphics API),使其能够同时支持DirectX 12、Vulkan、OpenGL等多种图形API。 + +Unity的核心设计理念: +- **分层架构**:上层应用与底层API完全解耦 +- **CommandBuffer**:使用命令缓冲模式,延迟执行渲染命令 +- **资源绑定抽象**:统一的资源绑定接口,隐藏不同API的差异 + +### 1.2 架构概览 + +``` +┌─────────────────────────────────────────────────────────┐ +│ 应用层 / 渲染管线 │ +│ (RenderPass, DrawCall, Material) │ +├─────────────────────────────────────────────────────────┤ +│ CommandBuffer │ +│ (统一的渲染命令缓冲,类似Unity) │ +├─────────────────────────────────────────────────────────┤ +│ Graphics API │ +│ ┌────────────────┬────────────────┬────────────────┐ │ +│ │ GraphicsAPI │ GraphicsAPI │ GraphicsAPI │ │ +│ │ (D3D12) │ (Vulkan) │ (OpenGL) │ │ +│ └────────────────┴────────────────┴────────────────┘ │ +└─────────────────────────────────────────────────────────┘ +``` + +--- + +## 二、核心接口设计 + +### 2.1 CommandBuffer(命令缓冲) + +Unity的CommandBuffer是渲染命令的核心抽象,本设计采用相同概念。 + +```cpp +namespace XCEngine { +namespace Graphics { + +// 前向声明 +class ComputeBuffer; +class ComputeShader; +class Material; +class Mesh; +class ComputeProgram; +class RenderTexture; +class Texture; +class Shader; + +// ==================== 基本类型定义 ==================== + +struct Rect { + float x, y, width, height; + Rect() : x(0), y(0), width(0), height(0) {} + Rect(float x, float y, float w, float h) : x(x), y(y), width(w), height(h) {} +}; + +using byte = uint8_t; + +// 命令缓冲类 +class CommandBuffer { +public: + CommandBuffer(); + ~CommandBuffer(); + + // ==================== 状态设置 ==================== + + // 设置渲染管线/程序 + void SetRenderProgram(ComputeProgram* program); + void SetMaterial(Material* material); + + // 设置纹理 + void SetTexture(Shader* shader, const char* name, Texture* texture); + void SetTexture(Shader* shader, int texureID, Texture* texture); + void SetTextures(Shader* shader, const char* name, std::vector& textures); + + // 设置矩阵/向量参数 + void SetMatrix(Shader* shader, const char* name, const float4x4& matrix); + void SetMatrixArray(Shader* shader, const char* name, const float4x4* matrices, int count); + void SetVector(Shader* shader, const char* name, const float4& vector); + void SetFloat(Shader* shader, const char* name, float value); + void SetInt(Shader* shader, const char* name, int value); + + // 全局参数(所有Shader可见) + void SetGlobalMatrix(const char* name, const float4x4& matrix); + void SetGlobalVector(const char* name, const float4& vector); + void SetGlobalFloat(const char* name, float value); + void SetGlobalTexture(const char* name, Texture* texture); + + // ==================== 渲染目标 ==================== + + // 设置渲染目标 + void SetRenderTarget(RenderTexture* color, RenderTexture* depth); + void SetRenderTarget(RenderTexture* color); + void SetRenderTarget(RenderTexture* color, int colorSlice, RenderTexture* depth, int depthSlice); + + // 激活渲染纹理(用于后续绘制) + void ActivateRenderTarget(RenderTexture* color, RenderTexture* depth); + + // ==================== 视口 ==================== + + void SetViewport(float x, float y, float width, float height); + void SetViewports(int count, Viewport* viewports); + void SetScissor(Rect rect); + void SetScissors(int count, Rect* rects); + + // ==================== 绘制 ==================== + + // 绘制网格 + void Draw(Mesh* mesh, int subMeshIndex = 0); + void DrawInstanced(Mesh* mesh, int subMeshIndex, int instanceCount); + void DrawMeshInstanced(Mesh* mesh, int subMeshIndex, int instanceCount, Material* material, int shaderPass = 0); + + // 绘制程序(Compute Shader) + void DispatchCompute(ComputeShader* shader, int threadGroupsX, int threadGroupsY, int threadGroupsZ); + + // 间接绘制 + void DrawMeshInstancedIndirect(Mesh* mesh, ComputeBuffer* argsBuffer, int argsOffset = 0); + + // ==================== 清除 ==================== + + void ClearRenderTarget(bool clearColor, bool clearDepth, bool clearStencil); + void ClearColor(const float4& color); + void ClearDepth(float depth); + void ClearStencil(int stencil); + + // ==================== 纹理操作 ==================== + + // 复制纹理 + void CopyTexture(Texture* src, Texture* dst); + void CopyTexture(Texture* src, int srcElement, int srcMip, int srcX, int srcY, int srcZ, + Texture* dst, int dstElement, int dstMip, int dstX, int dstY, int dstZ, + int width, int height, int depth); + + // 异步读取纹理 + void AsyncReadPixels(RenderTexture* source, Rect rect, TextureFormat format, bool activeCube); + + // ==================== 计算着色器 ==================== + + void SetComputeBuffer(ComputeShader* shader, const char* name, ComputeBuffer* buffer); + + // ==================== 同步 ==================== + + void IssuePluginEvent(int eventID); + void Flush(); + + // ==================== 渲染状态设置 ==================== + + // 设置模板引用值 + void SetStencilRef(int ref); + + // 启用/禁用裁剪 + void EnableScissor(); + void DisableScissor(); + + // 渲染目标(立即模式,不记录命令) + void SetRenderTargetImmediate(RenderTexture* color, RenderTexture* depth); + void SetRenderTargetImmediate(RenderTexture* color); + + // 线条宽度 + void SetLineWidth(float width); + + // 视口变换矩阵 + void SetViewTransform(const float4x4& view, const float4x4& projection); + void SetViewTransform(const float4x4& view, const float4x4& projection, const float4x4& brdf); + + // ==================== Blit(后处理) ==================== + + void Blit(Material* material, RenderTexture* source, RenderTexture* dest); + void Blit(Material* material, RenderTexture* source, RenderTexture* dest, int pass); + void Blit(Material* material, RenderTexture* source, RenderTexture* dest, int pass, int lodLevel); + + // ==================== 延迟执行 ==================== + + // 执行此CommandBuffer + void Execute(); + void Execute(CommandBuffer* other); + + // 立即执行(可选) + void ExecuteImmediate(); +}; + +// 全局命令缓冲 +CommandBuffer* GetMainCommandBuffer(); + +} // namespace Graphics +} // namespace XCEngine +``` + +### 2.2 GraphicsDevice(图形设备) + +Unity使用GraphicsDevice代表底层图形设备,本设计采用相同概念。 + +```cpp +namespace XCEngine { +namespace Graphics { + +// 图形API类型 +enum class GraphicsAPI { + Direct3D12, + Vulkan, + OpenGL, + OpenGLES3, + Metal +}; + +// 设备能力 +struct DeviceCapabilities { + bool supportsComputeShaders; + bool supportsGeometryShaders; + bool supportsTessellation; + bool supportsRaytracing; + bool supportsMeshShaders; + bool supportsNonPow2Textures; + bool supportsRenderTargetFloat; + bool supportsHDR; + int maxTextureSize; + int maxRenderTextureSize; + int maxCubemapSize; + int maxColorAttachments; + int maxComputeBuffers; + int maxComputeBufferSize; + int maxVertexAttributes; +}; + +// 纹理格式信息 +struct TextureFormatInfo { + TextureFormat format; + bool isSupported; + int bitsPerPixel; + bool isColor; + bool isDepth; + bool isPacked; + bool isCompressed; +}; + +// 图形设备接口 +class GraphicsDevice { +public: + virtual ~GraphicsDevice() = default; + + // 设备信息 + virtual GraphicsAPI GetAPI() const = 0; + virtual const char* GetDeviceName() const = 0; + virtual const DeviceCapabilities& GetCapabilities() const = 0; + + // 创建资源 + virtual Texture* CreateTexture(const TextureDescriptor& desc) = 0; + virtual RenderTexture* CreateRenderTexture(const RenderTextureDescriptor& desc) = 0; + virtual ComputeBuffer* CreateComputeBuffer(const ComputeBufferDescriptor& desc) = 0; + virtual Mesh* CreateMesh() = 0; + virtual ComputeShader* CreateComputeShader(const void* source, int sourceLength) = 0; + virtual ComputeProgram* CreateComputeProgram(ComputeShader* computeShader) = 0; + virtual Material* CreateMaterial(Shader* shader) = 0; + virtual Shader* CreateShader(const ShaderSource& source) = 0; + + // 命令缓冲管理 + virtual CommandBuffer* CreateCommandBuffer() = 0; + virtual CommandBuffer* GetTempCommandBuffer() = 0; + virtual void ReleaseTempCommandBuffer(CommandBuffer* cmd) = 0; + virtual void SubmitCommandBuffer(CommandBuffer* cmd) = 0; + + // 同步 + virtual void WaitForIdle() = 0; + + // 特性检测 + virtual bool SupportsTextureFormat(TextureFormat format) const = 0; + virtual bool SupportsVertexFormat(VertexAttribute format) const = 0; + + // 纹理格式信息 + virtual TextureFormatInfo GetTextureFormatInfo(TextureFormat format) const = 0; + + // 性能统计 + virtual void ResetStatistics() = 0; + virtual void GetStatistics() const = 0; +}; + +// 工厂函数 +GraphicsDevice* CreateGraphicsDevice(GraphicsAPI api, void* windowHandle = nullptr); +void DestroyGraphicsDevice(GraphicsDevice* device); +GraphicsAPI GetDefaultGraphicsAPI(); +std::vector GetAvailableGraphicsAPIs(); + +} // namespace Graphics +} // namespace XCEngine +``` + +### 2.3 Texture(纹理) + +```cpp +namespace XCEngine { +namespace Graphics { + +enum class TextureFormat { + // 颜色格式 + Alpha8, + ARGB4444, + RGB24, + RGBA32, + ARGB32, + RGB565, + DXT1, + DXT5, + RGBA4444, + BGRA32, + FloatRGHalf, + FloatRGBAHalf, + FloatRGBA, + FloatR, + HalfR, + IntR, + IntRG, + IntRGB, + IntRGBA, + DXT1Crunched, + DXT5Crunched, + RGBCrunched, + RGBACrunched, + + // 深度格式 + Depth16, + Depth24, + Depth24Stencil8, + Depth32Float, + Depth32FloatStencil8, + + // 阴影格式 + Shadowmap16, + Shadowmap24, + + // HDR + RGB9E5, + RG11B10Float, + RGB10A2, + + // YUV + YUV422, + YUV420 +}; + +enum class TextureDimension { + None, + Texture2D, + Texture3D, + Texture2DArray, + TextureCube, + TextureCubeArray +}; + +enum class TextureWrapMode { + Repeat, + Clamp, + Mirror, + Border +}; + +enum class TextureFilterMode { + Point, + Bilinear, + Trilinear, + Anisotropic +}; + +enum class TextureUsage { + Default = 0, + RenderTarget = 1, + DepthStencil = 2, + Memoryless = 3, + Staging = 4 +}; + +struct TextureDescriptor { + int width; + int height; + int depth; + int mipmapLevels; + int anisoLevel; + TextureFilterMode filterMode; + TextureWrapMode wrapMode; + TextureFormat format; + TextureDimension dimension; + TextureUsage usage; + bool enableRandomWrite; + bool useMipMap; + bool autoGenerateMipMaps; +}; + +class Texture { +public: + virtual ~Texture() = default; + + // 属性 + virtual int GetWidth() const = 0; + virtual int GetHeight() const = 0; + virtual int GetDepth() const = 0; + virtual int GetMipmapLevels() const = 0; + virtual TextureFormat GetFormat() const = 0; + virtual TextureDimension GetDimension() const = 0; + + // 过滤模式 + virtual void SetFilterMode(TextureFilterMode mode) = 0; + virtual TextureFilterMode GetFilterMode() const = 0; + + // 纹理坐标包装模式 + virtual void SetWrapMode(TextureWrapMode mode) = 0; + virtual TextureWrapMode GetWrapMode() const = 0; + + // 各向异性过滤 + virtual void SetAnisoLevel(int level) = 0; + virtual int GetAnisoLevel() const = 0; + + // MipMap + virtual void GenerateMipMaps() = 0; + virtual void SetAnisotropicFiltering(float min, float max) = 0; + + // 像素数据 + virtual void SetData(const void* data, int mipLevel = 0) = 0; + virtual void GetData(void* data, int mipLevel = 0) = 0; + + // 底层句柄 + virtual void* GetNativeTexturePtr() = 0; + virtual void* GetNativeTexturePtr(int target) = 0; +}; + +} // namespace Graphics +} // namespace XCEngine +``` + +### 2.4 RenderTexture(渲染纹理) + +```cpp +namespace XCEngine { +namespace Graphics { + +enum class RenderTextureFormat { + ARGB32, + ARGBHalf, + ARGBFloat, + RGHalf, + RGFloat, + RFloat, + Int, + Long, + Depth, + ARGBInt, + RGBAUShort, + RGBA16, + RGB10A2, + R8, + RG16, + R16, + RGHalf, + RG16, + R8Int, + RG8Int, + R16Int, + R32Int, + RGBA8, + RFloat, + RGHalf, + RHalf +}; + +enum class RenderTextureMemoryless { + None, + Depth, + Color +}; + +struct RenderTextureDescriptor { + int width; + int height; + int volumeDepth; + int mipCount; + int depthBufferBits; + RenderTextureFormat colorFormat; + RenderTextureFormat depthFormat; + int stencilFormat; + int antiAliasing; + bool enableRandomWrite; + bool useMipMap; + bool sRGB; + TextureDimension dimension; + RenderTextureMemoryless memoryless; + bool bindMSRenderTarget; + bool bindMSDepthSurface; + bool useDynamicscale; + bool forceIntoRT; +}; + +class RenderTexture : public Texture { +public: + virtual ~RenderTexture() = default; + + // 创建/释放 + virtual bool Create() = 0; + virtual void Release() = 0; + + // 是否有效 + virtual bool IsCreated() const = 0; + virtual bool IsDestroyed() const = 0; + + // 颜色缓冲 + virtual Texture* GetColorBuffer() = 0; + virtual void SetColorBuffer(Texture* color) = 0; + + // 深度缓冲 + virtual Texture* GetDepthBuffer() = 0; + virtual void SetDepthBuffer(Texture* depth) = 0; + + // 深度模板 + virtual int GetDepthBufferBits() const = 0; + + // MSAA + virtual int GetAntiAliasing() const = 0; + virtual void SetAntiAliasing(int aa) = 0; + + // 纹理数量 + virtual int GetVolumeDepth() const = 0; + virtual int GetMipMapLevelCount() const = 0; + + // 维度 + virtual TextureDimension GetDimension() const = 0; + + // 是否使用MipMap + virtual bool GetMipMap() const = 0; + virtual void SetMipMap(bool value) = 0; + + // sRGB读写 + virtual bool GetSRGBRead() const = 0; + virtual void SetSRGBRead(bool value) = 0; + virtual bool GetSRGBWrite() const = 0; + virtual void SetSRGBWrite(bool value) = 0; + + // 临时渲染纹理 + static RenderTexture* GetTemporary(const RenderTextureDescriptor& desc); + static void ReleaseTemporary(RenderTexture* rt); + + // ==================== 生命周期 ==================== + + // 初始化/反初始化 + virtual void Initialize() = 0; + virtual void Deinitialize() = 0; + virtual bool IsInitialized() const = 0; + + // 创建/销毁(替代构造函数) + virtual bool Create() = 0; + virtual void Destroy() = 0; + + // 是否有效 + virtual bool IsCreated() const = 0; + virtual bool IsDestroyed() const = 0; + + // 描述符 + virtual void* GetDescriptor() = 0; + + // 目标纹理 + virtual void SetTargetTexture(Texture* tex) = 0; + virtual Texture* GetTargetTexture() = 0; + + // ==================== 激活/解析 ==================== + + // 激活/停用 + virtual void Activate() = 0; + virtual void Resolve() = 0; + virtual void Resolve(Texture* target, int mipLevel = 0) = 0; +}; + +} // namespace Graphics +} // namespace XCEngine +``` + +### 2.5 ComputeBuffer(计算缓冲) + +```cpp +namespace XCEngine { +namespace Graphics { + +enum class ComputeBufferType { + Default, + Raw, + Append, + Counter, + DrawIndirect, + Structured, + ByteAddress +}; + +enum class ComputeBufferUsage { + Default = 0, + Dynamic = 1, + Immutable = 2, + Staging = 3 +}; + +struct ComputeBufferDescriptor { + int count; + int stride; + ComputeBufferType type; + ComputeBufferUsage usage; +}; + +class ComputeBuffer { +public: + virtual ~ComputeBuffer() = default; + + // 属性 + virtual int GetCount() const = 0; + virtual int GetStride() const = 0; + virtual ComputeBufferType GetBufferType() const = 0; + + // 数据操作 + virtual void SetData(const void* data) = 0; + virtual void GetData(void* data) = 0; + virtual void SetCounterValue(int counterValue) = 0; + + // 原子操作(用于Append/Counter类型) + virtual void Begin() = 0; // 开始计数 + virtual void End() = 0; // 结束计数 + virtual int GetCounterValue() = 0; + + // 有效性检查 + virtual bool IsValid() const = 0; + + // 底层句柄 + virtual void* GetNativeBufferPtr() = 0; +}; + +} // namespace Graphics +} // namespace XCEngine +``` + +### 2.6 Shader与ComputeShader + +```cpp +namespace XCEngine { +namespace Graphics { + +// Shader属性类型 +enum class ShaderPropertyType { + Color, + Vector, + Float, + Range, + Texture +}; + +struct ShaderProperty { + std::string name; + ShaderPropertyType type; + int nameID; + float defaultValue; + float defaultMin; + float defaultMax; +}; + +// Shader编译结果 +struct ShaderCompilationResult { + bool success; + std::string errorMessage; + int line; + std::vector errors; + std::vector warnings; +}; + +// Shader源 +struct ShaderSource { + const char* code; + const char* filename; + const char* entryPoint; + ShaderLanguage language; +}; + +// Shader语言 +enum class ShaderLanguage { + HLSL, + GLSL, + SPIRV, + DXIL +}; + +// Shader类型 +enum class ShaderType { + Vertex, + Fragment, + Geometry, + Compute, + Hull, + Domain, + RayGeneration, + RayIntersection, + RayMiss, + RayClosestHit +}; + +class Shader { +public: + virtual ~Shader() = default; + + // 属性 + virtual const char* GetName() const = 0; + virtual int GetPropertyCount() const = 0; + virtual ShaderProperty GetProperty(int index) const = 0; + virtual int FindPropertyIndex(const char* name) const = 0; + virtual ShaderPropertyType GetPropertyType(int nameID) const = 0; + + // 编译 + virtual bool IsSupported() const = 0; + virtual bool IsValid() const = 0; + virtual bool Compile(const char* entryPoint, ShaderType type) = 0; + + // Pass数量 + virtual int GetPassCount() const = 0; + + // 查找属性 + virtual int FindPropertyIndexByName(const char* name) const = 0; + + // 关键字 + virtual void DisableKeyword(const char* keyword) = 0; + virtual void EnableKeyword(const char* keyword) = 0; + virtual bool IsKeywordEnabled(const char* keyword) const = 0; + + // 获取Shader变体数量 + virtual int GetVariantCount() const = 0; + virtual int GetVariantCount(int pass) const = 0; + + // 设置全局关键词 + static void EnableKeywordGlobal(const char* keyword); + static void DisableKeywordGlobal(const char* keyword); + + // 预编译 + virtual void Precompile() = 0; +}; + +// Compute Shader +class ComputeShader : public Shader { +public: + virtual ~ComputeShader() = 0; + + // 内核 + virtual const char* GetKernelName() const = 0; + virtual void SetKernelArg(const char* argName, const void* data, int dataSize) = 0; + virtual void SetTexture(const char* argName, Texture* texture) = 0; + virtual void SetBuffer(const char* argName, ComputeBuffer* buffer) = 0; + + // 线程组大小 + virtual int GetKernelThreadGroupSizeX() const = 0; + virtual int GetKernelThreadGroupSizeY() const = 0; + virtual int GetKernelThreadGroupSizeZ() const = 0; +}; + +// Compute Program +class ComputeProgram { +public: + virtual ~ComputeProgram() = 0; + + virtual ComputeShader* GetKernel() const = 0; + virtual bool IsValid() const = 0; + virtual void GetKernelThreadGroupSizes(size_t& x, size_t& y, size_t& z) const = 0; +}; + +} // namespace Graphics +} // namespace XCEngine +``` + +### 2.7 Material与RenderState + +```cpp +namespace XCEngine { +namespace Graphics { + +// 混合模式 +enum class BlendMode { + Alpha, + AlphaPremultiply, + Additive, + Multiply, + Overlay, + Opaque, + Transparent, + Custom +}; + +// 混合因子 +enum class BlendFactor { + Zero, + One, + SrcColor, + InvSrcColor, + SrcAlpha, + InvSrcAlpha, + DstAlpha, + InvDstAlpha, + DstColor, + InvDstColor, + SrcAlphaSat, + BlendFactor, + InvBlendFactor, + Src1Color, + InvSrc1Color, + Src1Alpha, + InvSrc1Alpha +}; + +// 混合操作 +enum class BlendOp { + Add, + Subtract, + ReverseSubtract, + Min, + Max +}; + +// 比较函数 +enum class CompareFunction { + Disabled, + Never, + Less, + Equal, + LessEqual, + Greater, + NotEqual, + GreaterEqual, + Always +}; + +// 模板操作 +enum class StencilOp { + Keep, + Zero, + Replace, + IncrSat, + DecrSat, + Invert, + IncrWrap, + DecrWrap +}; + +// 背面剔除 +enum class CullMode { + Off, + Front, + Back +}; + +// 深度写入 +enum class DepthWrite { + Less, + LessEqual, + Equal, + GreaterEqual, + Greater, + Always +}; + +// 颜色写入 +enum class ColorWriteMask { + Alpha = 1, + Blue = 2, + Green = 4, + Red = 8, + All = 15 +}; + +struct RenderState { + // 混合 + BlendMode blend; + BlendFactor srcBlend; + BlendFactor dstBlend; + BlendOp blendOp; + BlendFactor srcBlendAlpha; + BlendFactor dstBlendAlpha; + BlendOp blendOpAlpha; + ColorWriteMask colorWriteMask; + + // 深度 + bool depthWrite; + bool depthTest; + CompareFunction depthFunc; + + // 模板 + bool stencil; + CompareFunction stencilCompare; + StencilOp stencilPass; + StencilOp stencilFail; + StencilOp stencilZFail; + byte stencilReadMask; + byte stencilWriteMask; + byte stencilRef; + + // 背面剔除 + CullMode cullMode; + bool frontFaceCCW; + + // 深度偏移 + bool depthBias; + float slopeScaledDepthBias; + float depthBiasClamp; + float depthBiasConstantFactor; + + // 渲染队列 + int renderQueue; +}; + +// ==================== Pass(渲染通道) ==================== +// Unity中每个Material有多个Pass,每个Pass独立渲染 +class Pass { +public: + virtual ~Pass() = default; + + // 渲染状态 + virtual const RenderState& GetRenderState() const = 0; + virtual void SetRenderState(const RenderState& state) = 0; + + // Shader + virtual Shader* GetShader() const = 0; + virtual void SetShader(Shader* shader) = 0; + + // 混合 + virtual void SetBlendMode(BlendMode mode) = 0; + + // 模板 + virtual void SetStencil(const RenderState& state) = 0; + + // 渲染队列覆盖 + virtual void SetRenderQueue(int queue) = 0; + virtual int GetRenderQueue() const = 0; +}; + +// ==================== Material(材质) ==================== + +class Material { +public: + virtual ~Material() = default; + + // Shader + virtual Shader* GetShader() const = 0; + virtual void SetShader(Shader* shader) = 0; + + // Pass管理 + virtual int GetPassCount() const = 0; + virtual Pass* GetPass(int index) = 0; + virtual Pass* CreatePass(const char* name = nullptr) = 0; + virtual void ReleasePass(Pass* pass) = 0; + virtual const char* GetPassName(int index) const = 0; + virtual int FindPass(const char* name) const = 0; + virtual void SetPass(int pass) = 0; + + // 快捷方法(作用于当前Pass) + virtual void SetInt(const char* name, int value) = 0; + virtual void SetFloat(const char* name, float value) = 0; + virtual void SetFloatArray(const char* name, const float* values, int count) = 0; + virtual void SetVector(const char* name, const float4& value) = 0; + virtual void SetVectorArray(const char* name, const float4* values, int count) = 0; + virtual void SetMatrix(const char* name, const float4x4& value) = 0; + virtual void SetMatrixArray(const char* name, const float4x4* values, int count) = 0; + virtual void SetTexture(const char* name, Texture* value) = 0; + + // 渲染状态(快捷方法,作用于当前Pass) + virtual RenderState GetRenderState() const = 0; + virtual void SetRenderState(const RenderState& state) = 0; + virtual void SetOverrideTag(const char* tag) = 0; + + // 渲染队列 + virtual int GetRenderQueue() const = 0; + virtual void SetRenderQueue(int queue) = 0; + virtual void SetRenderQueue(int queue, int subqueueShift) = 0; + + // 关键字 + virtual void EnableKeyword(const char* keyword) = 0; + virtual void DisableKeyword(const char* keyword) = 0; + virtual bool IsKeywordEnabled(const char* keyword) const = 0; + virtual void ShaderKeywordsFromGlobal() = 0; + + // Pass启用 + virtual void SetPassEnabled(const char* passName, bool enabled) = 0; + virtual bool IsPassEnabled(const char* passName) const = 0; + + // 复制 + virtual Material* Clone() = 0; +}; + +} // namespace Graphics +} // namespace XCEngine +``` + +### 2.8 Mesh(网格) + +```cpp +namespace XCEngine { +namespace Graphics { + +enum class MeshTopology { + Points, + Lines, + LineStrip, + Triangles, + TriangleStrip, + Quads +}; + +enum class MeshIndexFormat { + Index16, + Index32 +}; + +class Mesh { +public: + virtual ~Mesh() = 0; + + // 顶点数据 + virtual void SetVertices(const float3* vertices, int count) = 0; + virtual void SetVertices(const void* vertices, int count, const VertexAttribute* attributes, int attributeCount) = 0; + virtual void GetVertices(float3* vertices) = 0; + virtual int GetVertexCount() const = 0; + + // 索引数据 + virtual void SetIndices(const uint16_t* indices, int count) = 0; + virtual void SetIndices(const uint32_t* indices, int count) = 0; + virtual void GetIndices(uint16_t* indices) = 0; + virtual void GetIndices(uint32_t* indices) = 0; + virtual int GetIndexCount() const = 0; + virtual MeshIndexFormat GetIndexFormat() const = 0; + + // 顶点属性 + virtual void SetTangents(const float4* tangents) = 0; + virtual void SetNormals(const float3* normals) = 0; + virtual void SetColors(const Color* colors) = 0; + virtual void SetColors(const float4* colors) = 0; + virtual void SetUVs(int channel, const float2* uvs) = 0; + virtual void SetUVs(int channel, const float3* uvs) = 0; + virtual void SetBoneWeights(const float4* weights, const uint8_t* indices) = 0; + + // 子网格 + virtual void SetSubmeshCount(int count) = 0; + virtual void SetSubmesh(int index, int startIndex, int indexCount, int baseVertex) = 0; + + // 边界 + virtual void RecalculateBounds() = 0; + virtual AABB GetBounds() const = 0; + + // 顶点缓冲区 + virtual int GetVertexBufferCount() const = 0; + virtual VertexBuffer* GetVertexBuffer(int index) const = 0; + + // 索引缓冲区 + virtual VertexBuffer* GetIndexBuffer() const = 0; + + // 拓扑 + virtual void SetTopology(MeshTopology topology) = 0; + virtual MeshTopology GetTopology() const = 0; + + // 动态标记(频繁更新) + virtual void MarkDynamic() = 0; + virtual bool IsDynamic() const = 0; + + // 上传 + virtual void UploadMeshData(bool markNoLongerReadable = false) = 0; + virtual void Clear() = 0; + + // 获取子网格信息 + virtual int GetSubmeshCount() const = 0; + virtual void GetSubmesh(int index, int& startIndex, int& indexCount, int& baseVertex) const = 0; +}; + +} // namespace Graphics +} // namespace XCEngine +``` + +### 2.9 辅助类型 + +```cpp +namespace XCEngine { +namespace Graphics { + +// 顶点属性格式 +enum class VertexAttributeFormat { + Float, + Float2, + Float3, + Float4, + Half, + Half2, + Half4, + Int, + Int2, + Int3, + Int4, + UInt, + UInt2, + UInt3, + UInt4, + Color, + Color32, + Short, + Short2, + Short4, + UShort, + UShort2, + UShort4 +}; + +// 顶点输入描述 +struct VertexAttribute { + std::string semantic; + int semanticIndex; + VertexAttributeFormat format; + int stream; + int offset; +}; + +// 顶点布局 +class VertexLayout { +public: + void AddAttribute(const char* semantic, int semanticIndex, VertexAttributeFormat format); + void AddAttribute(const char* semantic, VertexAttributeFormat format); + const std::vector& GetAttributes() const; + int GetStride() const; +}; + +// 视口 +struct Viewport { + float x, y; + float width, height; + float minDepth, maxDepth; + + Viewport() : x(0), y(0), width(0), height(0), minDepth(0), maxDepth(1) {} + Viewport(float x, float y, float w, float h) : x(x), y(y), width(w), height(h), minDepth(0), maxDepth(1) {} +}; + +// 矩阵和向量(使用现有Math库) +using float4x4 = XCEngine::Math::Matrix4; +using float4 = XCEngine::Math::Vector4; +using float3 = XCEngine::Math::Vector3; +using float2 = XCEngine::Math::Vector2; +using Color = XCEngine::Math::Color; +using AABB = XCEngine::Math::AABB; + +} // namespace Graphics +} // namespace XCEngine +``` + +--- + +## 三、后端实现 + +### 3.1 D3D12后端 + +```cpp +namespace XCEngine { +namespace Graphics { +namespace D3D12 { + +class D3D12GraphicsDevice : public GraphicsDevice { +public: + D3D12GraphicsDevice(ID3D12Device* device, IDXGIFactory4* factory); + ~D3D12GraphicsDevice() override; + + GraphicsAPI GetAPI() const override { return GraphicsAPI::Direct3D12; } + const char* GetDeviceName() const override; + const DeviceCapabilities& GetCapabilities() const override; + + Texture* CreateTexture(const TextureDescriptor& desc) override; + RenderTexture* CreateRenderTexture(const RenderTextureDescriptor& desc) override; + ComputeBuffer* CreateComputeBuffer(const ComputeBufferDescriptor& desc) override; + Mesh* CreateMesh() override; + ComputeShader* CreateComputeShader(const void* source, int sourceLength) override; + ComputeProgram* CreateComputeProgram(ComputeShader* computeShader) override; + Material* CreateMaterial(Shader* shader) override; + Shader* CreateShader(const ShaderSource& source) override; + + CommandBuffer* CreateCommandBuffer() override; + void SubmitCommandBuffer(CommandBuffer* cmd) override; + + void WaitForIdle() override; + bool SupportsTextureFormat(TextureFormat format) const override; + bool SupportsVertexFormat(VertexAttribute format) const override; + +private: + ComPtr m_device; + ComPtr m_factory; + ComPtr m_commandQueue; + DeviceCapabilities m_capabilities; +}; + +class D3D12CommandBuffer : public CommandBuffer { +public: + D3D12CommandBuffer(ID3D12Device* device); + ~D3D12CommandBuffer() override; + + // 实现CommandBuffer接口... + // 使用D3D12的ID3D12GraphicsCommandList + +private: + ComPtr m_commandList; + std::vector> m_resources; +}; + +} // namespace D3D12 +} // namespace Graphics +} // namespace XCEngine +``` + +### 3.2 OpenGL后端 + +```cpp +namespace XCEngine { +namespace Graphics { +namespace OpenGL { + +class OpenGLGraphicsDevice : public GraphicsDevice { +public: + OpenGLGraphicsDevice(void* windowHandle); + ~OpenGLGraphicsDevice() override; + + GraphicsAPI GetAPI() const override { return GraphicsAPI::OpenGL; } + const char* GetDeviceName() const override; + const DeviceCapabilities& GetCapabilities() const override; + + // 实现工厂方法... + +private: + void* m_windowHandle; + DeviceCapabilities m_capabilities; +}; + +class OpenGLCommandBuffer : public CommandBuffer { +public: + OpenGLCommandBuffer(); + ~OpenGLCommandBuffer() override; + + // 实现CommandBuffer接口 + // OpenGL直接执行,无需命令列表 + // 可以使用Display List或记录命令 + +private: + GLuint m_vao; + std::unordered_map m_boundTextures; +}; + +} // namespace OpenGL +} // namespace Graphics +} // namespace XCEngine +``` + +--- + +## 四、目录结构 + +``` +engine/ +├── include/XCEngine/ +│ └── Graphics/ +│ ├── CommandBuffer.h # 命令缓冲 +│ ├── GraphicsDevice.h # 图形设备 +│ ├── Texture.h # 纹理 +│ ├── RenderTexture.h # 渲染纹理 +│ ├── ComputeBuffer.h # 计算缓冲 +│ ├── Shader.h # Shader +│ ├── ComputeShader.h # Compute Shader +│ ├── Material.h # 材质 +│ ├── Mesh.h # 网格 +│ ├── VertexLayout.h # 顶点布局 +│ ├── Types.h # 类型定义 +│ └── Enums.h # 枚举定义 +│ +└── src/ + └── Graphics/ + ├── D3D12/ + │ ├── D3D12Device.cpp + │ ├── D3D12CommandBuffer.cpp + │ ├── D3D12Texture.cpp + │ └── ... + │ + ├── OpenGL/ + │ ├── OpenGLDevice.cpp + │ ├── OpenGLCommandBuffer.cpp + │ ├── OpenGLTexture.cpp + │ └── ... + │ + └── Common/ + └── ... +``` + +--- + +## 五、使用示例 + +```cpp +// 创建图形设备 +GraphicsDevice* device = CreateGraphicsDevice(GraphicsAPI::D3D12, hwnd); + +// 创建纹理 +TextureDescriptor texDesc; +texDesc.width = 1024; +texDesc.height = 1024; +texDesc.format = TextureFormat::RGBA32; +texDesc.dimension = TextureDimension::Texture2D; +Texture* texture = device->CreateTexture(texDesc); + +// 创建Compute Shader +ComputeShader* computeShader = device->CreateComputeShader(csSource, csSourceLen); + +// 创建Compute Program +ComputeProgram* computeProgram = device->CreateComputeProgram(computeShader); + +// 创建CommandBuffer +CommandBuffer* cmd = device->CreateCommandBuffer(); + +// 渲染命令 +cmd->SetComputeTexture(computeShader, "MainTex", texture); +cmd->DispatchCompute(computeShader, 32, 32, 1); + +// 执行 +device->SubmitCommandBuffer(cmd); +``` + +--- + +*文档版本:2.0* +*更新日期:2026-03-16* diff --git a/docs/plan/开题报告和任务书/DXR_Volumetric_Rendering_Research_Report.md b/docs/plan/开题报告和任务书/DXR_Volumetric_Rendering_Research_Report.md new file mode 100644 index 0000000..cb25d71 --- /dev/null +++ b/docs/plan/开题报告和任务书/DXR_Volumetric_Rendering_Research_Report.md @@ -0,0 +1,297 @@ +# DirectX Raytracing (DXR) 体积渲染技术调研报告 + +## 一、DXR基本能力与工作原理 + +### 1.1 什么是DirectX Raytracing (DXR) + +DirectX Raytracing(DXR)是Microsoft在DirectX 12中引入的光线追踪API,于2018年随Windows 10 1809版本正式发布。DXR代表了实时图形渲染的重大技术飞跃,它使得在游戏和应用程序中实现电影级真实感渲染成为可能此前这一直是离线渲染领域的专利。 + +DXR的核心设计目标是提供硬件加速的光线追踪能力,让开发者能够在可交互的帧率下实现全局光照、反射、阴影等高级渲染效果。作为DirectX 12 Ultimate的一部分,DXR现已得到业界广泛支持,包括NVIDIA、AMD、Intel在内的主流GPU厂商都提供了兼容的驱动程序。 + +### 1.2 DXR核心组件架构 + +DXR的技术架构由几个关键组件构成,每个组件都在光线追踪流程中扮演着不可或缺的角色: + +**Acceleration Structure(加速结构)** 是DXR中最核心的数据结构。加速结构是一种层次化的边界体积层次(BVH),用于在GPU上高效地组织场景几何体数据。它将场景中的三角形组织成树形结构,使得光线与场景的求交测试可以从O(n)降低到O(log n)的复杂度。DXR支持两种类型的加速结构:Top-Level AS(TLAS)用于组织多个Bottom-Level AS,可以高效处理动态场景中的对象更新;Bottom-Level AS(BLAS)用于组织单个几何体的三角形数据。这种双层设计允许开发者仅更新发生变化的对象对应的BLAS,而无需重建整个场景的加速结构,这对于实时应用至关重要。 + +**Shader Table(着色器表)** 是DXR中用于将光线追踪管道中的各种着色器与场景对象关联起来的数据结构。Shader Table本质上是一个包含着色器标识符和着色器参数的GPU缓冲区,开发者可以通过它为不同的几何体指定不同的材质属性、反射特性或自定义着色器逻辑。这种设计使得DXR具有高度的灵活性,能够支持复杂多样的材质和渲染效果。 + +**Ray Dispatch(光线调度)** 是发起光线追踪计算的操作。通过DispatchRays,开发者可以指定光线生成着色器(Ray Generation Shader)的入口点,以及光线追踪管道的各项参数。GPU会根据这些配置启动大量的光线追踪计算单元,每个计算单元会执行相应的着色器代码来完成光线与场景的求交测试。 + +**Pipeline State Object(管道状态对象)** 定义了光线追踪管道的完整配置,包括各种着色器(光线生成着色器、命中着色器、未命中着色器、相交着色器)的编译状态,以及管道配置参数如最大递归深度等。 + +### 1.3 DXR着色器类型与光线追踪管道 + +DXR定义了一套专用的着色器类型来支持完整的光线追踪流程,每种着色器都有其特定的职责: + +**Ray Generation Shader(光线生成着色器)** 是光线追踪管道的起点,通常每个像素或每个采样点发射一条光线。开发者可以在此着色器中实现相机光线生成、抖动采样、反锯齿等逻辑。 + +**Intersection Shader(相交着色器)** 用于处理非三角形几何体的求交测试。通过自定义相交着色器,开发者可以实现程序化几何体(如球体、圆锥体)、体素数据或其他自定义图元的光线求交逻辑。这一功能对于体积渲染尤为重要,因为它允许直接在加速结构中表示体数据。 + +**AnyHit Shader(任意命中着色器)** 在光线与几何体求交时被调用,可用于执行透明材质测试、Alpha遮罩剔除等操作。DXR 1.1版本引入了更高效的Opacity Micromaps技术,可以硬件加速Alpha测试几何体的处理。 + +**ClosestHit Shader(最近命中着色器)** 当光线命中几何体时执行,通常用于计算表面的着色属性如漫反射、镜面反射、材质纹理查询等。 + +**Miss Shader(未命中着色器)** 当光线未命中任何几何体时执行,常用于实现环境映射、天空盒渲染或雾效等效果。 + +### 1.4 DXR版本演进与最新特性 + +自首次发布以来,DXR经历了多个版本的演进,持续引入新功能以提升光线追踪的效率和能力: + +DXR 1.0版本奠定了基础架构,提供了核心的光线追踪能力。从DXR 1.1开始,Microsoft引入了内联光线追踪(Inline Raytracing)功能,允许在普通计算着色器中直接调用TraceRay函数,而无需完整的射线追踪管道。这为混合渲染方案打开了大门,开发者可以在传统光栅化渲染中局部使用光线追踪来增强特定效果。 + +DXR 1.2版本(2025年GDC大会上发布)带来了多项重要更新:**Shader Execution Reordering(SER)** 允许应用层向GPU提供光线执行顺序的提示,使硬件能够更好地并行化光线执行,对于处理非相干光线(如间接照明)特别有效,NVIDIA在《Alan Wake 2》中的演示显示该技术可减少约三分之一的光线追踪开销。**Opacity Micromaps(OMMs)** 为Alpha测试几何体提供了硬件加速支持,使得树木、栅栏等复杂透明几何体的光线追踪更加高效。此外还有**打孔板(Per-primitive)着色器标识符**和**可加载管道**等改进。 + +## 二、DXR与体积渲染的兼容性分析 + +### 2.1 体积渲染概述 + +体积渲染是一种用于渲染具有体积属性的介质(如云、雾、烟、火、人体组织等)的技术。与传统基于表面的渲染不同,体积渲染需要考虑光线在穿过介质时的吸收、发射和散射现象。典型的体积渲染算法包括Ray Marching(光线步进)、体光线投射(Volume Ray Casting)和基于物理的体积散射等。 + +体积渲染的核心挑战在于处理可能占据整个空间的无边界介质,以及需要在光线穿过的每个位置进行采样和累积计算的特性。这些特性使得体积渲染在计算上极为密集,特别适合GPU并行处理。 + +### 2.2 DXR对体积渲染的原生支持程度 + +DXR本身并未为体积渲染提供专门的API或内置支持,但通过其灵活的扩展机制,开发者完全可以在DXR框架内实现体积渲染功能。关键在于如何有效地将体积数据表示为DXR可以处理的形式。 + +从架构角度看,DXR的Intersection Shader机制是实现体积渲染的核心。开发者可以编写自定义的相交着色器来处理体数据的求交测试,或者更常见地,使用程序化几何体(Procedural Geometry)来表示体积边界,然后结合Ray Marching在ClosestHit或Miss着色器中执行体积采样。 + +另一种常见方案是将体积渲染与传统的表面光线追踪相结合:使用DXR处理场景中的实体几何体(提供反射、阴影、全局光照等效果),而使用Compute Shader处理体积效果。这种混合方法在游戏开发中尤为常见,可以在视觉质量和性能之间取得良好平衡。 + +值得注意的是,NVIDIA在其RTX技术栈中提供了**Volumetric Fog**(体积雾)解决方案,这可以被视为DXR生态中体积渲染的一个参考实现。该方案利用硬件加速的VDB体素数据处理能力,实现了高效的体积雾效果。 + +### 2.3 在DXR中实现体积渲染的技术路径 + +在DXR框架内实现体积渲染主要有以下几种技术路径: + +**基于Intersection Shader的体数据求交**:通过编写自定义的相交着色器,可以直接在加速结构中表示体数据的边界。相交着色器负责计算光线与体数据边界盒的交点,并返回光线进入和离开体积的位置。随后可以在ClosestHit着色器中执行Ray Marching来累积体积属性。 + +**基于Procedural Geometry的程序化体积**:将程序化几何体添加到加速结构中,可以用于表示体积的边界表面。在ClosestHit着色器中,开发者可以实现更复杂的体积渲染逻辑,包括多层Ray Marching、体积光照计算等。 + +**混合渲染架构**:这是目前业界最常用的方法。使用DXR处理场景中的所有表面几何体,实现高质量的反射、阴影和全局光照;同时使用Compute Shader或Pixel Shader实现体积效果的渲染。这种方法可以充分利用DXR的硬件加速能力处理传统光线追踪效果,同时保持体积渲染的灵活性。 + +**内联光线追踪(Inline Raytracing)**:DXR 1.1引入的内联光线追踪允许在普通着色器中直接调用TraceRay函数,这为在Compute Shader中结合传统Ray Marching与DXR加速结构提供了便利。开发者可以使用内联光线追踪来查询场景中几何体的遮挡关系,用于体积渲染中的阴影计算等。 + +## 三、Acceleration Structure与NanoVDB的结合可能性 + +### 3.1 NanoVDB技术解析 + +NanoVDB是由NVIDIA开发的一种针对GPU优化的稀疏体素数据结构,最初作为OpenVDB的轻量级分支引入。NanoVDB的设计目标是提供高效的体数据存储和访问模式,特别适合GPU计算场景。 + +NanoVDB的核心特性包括:紧凑的内存布局采用分层结构,包括Root节点、Internal节点和Leaf节点,支持极高的空间稀疏性;GPU原生支持数据可以直接传输到GPU显存中而无需预处理或转换;多用途API支持访问密度值、法线、颜色等属性,适用于渲染和物理模拟等多种应用;快速的插入和删除操作支持动态体积数据的实时更新。 + +在渲染领域,NanoVDB被广泛用于体积云、烟雾、火焰等效果的实现。NVIDIA的Omniverse平台和多个游戏引擎都已集成了NanoVDB支持。 + +### 3.2 Acceleration Structure在体积渲染中的角色 + +DXR的Acceleration Structure本质上是针对三角形几何体优化的边界体积层次(BVH)结构。它通过层次化的包围盒组织来实现高效的光线-几何体求交。对于体积渲染数据,Acceleration Structure可以扮演以下角色: + +**体积边界表示**:可以将体积数据的边界盒作为加速结构中的几何体添加进去。这样DXR可以快速判断光线是否穿过体积区域,避免对空白空间的无效采样。 + +**多层加速结构组合**:对于同时包含表面几何体和体积数据的复杂场景,可以分别构建表面几何体的加速结构和体积边界的加速结构,通过Top-Level AS将它们组合在一起。这种设计允许DXR同时处理表面光线追踪(反射、阴影)和体积效果。 + +**空间查询加速**:Acceleration Structure的空间查询能力可以被体积渲染利用。例如,可以使用加速结构来查询体积中的光照遮挡,或者用于体积阴影的计算。 + +### 3.3 NanoVDB与Acceleration Structure结合的技术方案 + +将NanoVDB与DXR的Acceleration Structure结合使用存在若干技术路径: + +**方案一:NanoVDB作为纹理数据源,Acceleration Structure作为空间索引** + +这是最直接的结合方式。在这种架构中,NanoVDB存储实际的体数据(密度、颜色、法线等),而DXR的Acceleration Structure用于快速空间查询。具体的实现流程如下: + +首先,为场景中的表面几何体构建标准的Bottom-Level AS。其次,将体积边界(可以是简单的盒形或更复杂的凸包)作为程序化几何体添加到加速结构中。然后,在相应的着色器中,通过查询NanoVDB数据结构来获取体积属性:对于表面几何体,使用传统的着色器逻辑;对于体积边界,使用Ray Marching遍历NanoVDB数据结构进行采样累积。 + +这种方案的优点是充分利用了DXR的硬件光线追踪能力来处理场景几何体,同时NanoVDB提供了高效的体数据访问。缺点是体积边界需要预先定义,可能不够精确。 + +**方案二:完全基于Acceleration Structure的混合方法** + +这种方法将所有渲染元素都纳入加速结构管理。对于表面几何体使用标准的三角形加速;对于体积数据,可以使用程序化几何体表示体积边界,或者使用Instance Buffer来引用体积区域。 + +体积渲染的计算完全在Compute Shader中执行,使用NanoVDB作为数据源。DXR的加速结构仅用于快速的光线-场景求交查询,例如计算体积中的太阳光遮挡或实现体积阴影。 + +这种方案的优点是架构清晰,体积渲染的灵活性不受限制。缺点是需要额外的工作来同步DXR加速结构和NanoVDB数据。 + +**方案三:基于内联光线追踪的深度集成** + +DXR 1.1引入的内联光线追踪提供了更灵活的集成方案。开发者可以在Compute Shader中执行自定义的Ray Marching逻辑,同时使用TraceRay函数查询DXR加速结构来实现与场景几何体的交互(如体积阴影、间接光照等)。 + +具体实现时,在Compute Shader中为每个像素执行Ray Marching遍历NanoVDB数据;在Ray Marching的每个采样点,使用内联光线追踪查询场景几何体的遮挡情况,用于计算光照衰减;最终累积体积颜色和不透明度到输出缓冲区。 + +这种方案的优点是实现了DXR加速结构与NanoVDB的深度结合,可以产生更真实的体积渲染效果(包括体积阴影、多次散射等)。缺点是实现复杂度较高,需要处理两种渲染管道的同步和数据传递。 + +### 3.4 结合方案的性能考量 + +在设计NanoVDB与Acceleration Structure的结合方案时,以下性能因素需要重点考虑: + +**加速结构构建成本**:DXR的Acceleration Structure构建(尤其是Bottom-Level AS)是一个相对昂贵的操作。对于动态场景,可能需要采用增量更新策略或使用Instance层级的变换更新来避免全量重建。 + +**内存占用**:NanoVDB和Acceleration Structure都会占用GPU显存。对于大规模场景,需要评估内存预算并可能采用流式加载策略。 + +**数据同步开销**:当体积数据或场景几何体发生变化时,需要确保NanoVDB数据和DXR加速结构保持一致。这可能需要额外的CPU端协调逻辑。 + +**GPU带宽**:体积渲染通常需要高频的体数据访问。NanoVDB的数据布局已经针对GPU访问进行了优化,但在设计结合方案时仍需注意减少不必要的数据传输。 + +## 四、DXR体积渲染vs传统Compute Shader Ray Marching对比分析 + +### 4.1 两种技术路径的概述 + +**DXR体积渲染方案**是指利用DXR API和硬件加速光线追踪能力来实现体积渲染效果。这种方案的核心思想是:使用Acceleration Structure组织场景几何体,使用DXR着色器(Ray Generation、ClosestHit、Miss等)执行光线追踪逻辑,在着色器中结合Ray Marching实现体积效果。 + +**传统Compute Shader Ray Marching方案**是指使用Compute Shader直接执行Ray Marching算法来渲染体积效果。这种方案完全在Compute Shader中实现光线与体积数据的求交和累积,不依赖DXR的光线追踪硬件。 + +### 4.2 性能对比分析 + +**光线生成与调度效率**:DXR方案具有显著优势。DXR的硬件光线调度器经过专门优化,可以高效地生成和分发大量光线。传统Compute Shader需要手动管理线程组织和光线调度,效率相对较低。特别是在处理大规模并行光线时,DXR的硬件加速优势更为明显。 + +**空间查询效率**:DXR的Acceleration Structure对于场景几何体的空间查询具有极高的效率。当体积渲染需要与场景几何体交互(如计算体积阴影、遮挡)时,DXR可以快速完成这些查询。传统Compute Shader通常需要使用额外的加速结构(如BVH库或网格结构)来实现类似功能,增加了开发复杂度。 + +**灵活性与控制**:Compute Shader方案具有更高的灵活性。开发者可以完全控制Ray Marching的每个步骤,包括步长策略、早停条件、采样模式等。DXR方案受到管道结构的限制,虽然提供了足够的灵活性,但在某些极端定制场景下可能不如Compute Shader自由。 + +**混合渲染支持**:DXR方案在混合渲染场景中具有天然优势。可以轻松地将体积渲染与反射、全局光照、软阴影等DXR原生效果结合。Compute Shader方案需要额外的工作来集成这些效果。 + +**内存效率**:Compute Shader方案通常具有更小的内存占用,因为它不需要维护Acceleration Structure等额外数据结构。DXR的加速结构虽然经过了优化,但仍然会占用可观的显存,特别是在大规模复杂场景中。 + +### 4.3 画质对比分析 + +**阴影质量**:DXR方案可以提供物理准确的体积阴影。通过硬件加速的光线追踪,可以实现高质量的软阴影和多次散射效果。Compute Shader方案需要手动实现阴影光线计算,虽然可以达成类似效果,但计算成本较高。 + +**全局光照集成**:DXR可以更容易地实现体积与全局光照的集成。例如,体积可以接收来自场景几何体的间接光照,这是DXR原生支持的能力。Compute Shader方案需要额外的计算来模拟间接光照。 + +**抗锯齿与降噪**:两种方案都需要处理采样不足导致的噪声问题。DXR可以使用硬件降噪器或NVIDIA的Optix降噪库。Compute Shader方案通常需要使用基于屏幕空间的降噪方法。 + +### 4.4 开发复杂度对比 + +**API复杂度**:DXR API相对复杂,需要理解Acceleration Structure构建、Shader Table配置、管道状态对象等概念。Compute Shader Ray Marching的实现更接近传统的图形编程模式,对有图形编程经验的开发者更加友好。 + +**调试工具支持**:DXR有专门的调试工具支持,包括PIX for Windows和DirectX Graphics Developer Debugger。Compute Shader的调试工具更为成熟。 + +**跨平台兼容性**:DXR仅在Windows平台可用(通过DirectX 12)。Compute Shader是DirectX 12和Vulkan都支持的功能,具有更好的跨平台潜力。 + +### 4.5 适用场景建议 + +**推荐使用DXR体积渲染的场景**:需要与场景几何体进行复杂交互的体积效果;需要同时实现反射、全局光照等DXR原生效果;目标平台仅为Windows且硬件支持DXR;对性能要求较高,需要利用硬件光线追踪加速。 + +**推荐使用Compute Shader Ray Marching的场景**:体积效果独立于场景几何体;需要高度定制化的Ray Marching策略;需要跨平台支持(Windows/Linux/macOS);项目已有成熟的Compute Shader渲染管线。 + +**混合方案建议**:对于大多数实际应用,推荐采用混合方案。使用DXR处理场景中的表面几何体和传统光线追踪效果,使用Compute Shader处理体积渲染。这种方案可以兼得两种技术的优势。 + +## 五、现有DXR体积渲染示例与项目调研 + +### 5.1 Microsoft官方DXR示例 + +Microsoft的DirectX-Graphics-Samples GitHub仓库提供了丰富的DXR学习资源。虽然官方示例主要聚焦于基础光线追踪功能,但其中包含的若干示例对于理解DXR体积渲染具有重要参考价值: + +**D3D12RaytracingHelloWorld**:作为入门级示例,展示了DXR的基本设置流程,包括加速结构构建、Shader Table配置和光线调度。理解这个示例是开发更复杂渲染效果的基础。 + +**D3D12RaytracingProceduralGeometry**:展示了如何使用Intersection Shader实现程序化几何体。这一技术对于在DXR中实现体积渲染具有直接参考价值,因为程序化几何体可以用于表示体积边界。 + +**D3D12RaytracingRealTimeDenoisedAmbientOcclusion**:虽然聚焦于环境光遮罩,但展示了如何实现实时光线追踪降噪,这对于体积渲染中的噪声控制具有参考意义。 + +**D3D12RaytracingMiniEngineSample**:集成了DXR的MiniEngine示例,展示了更完整的渲染管线集成方案。 + +### 5.2 NVIDIA相关技术与示例 + +作为DXR硬件支持的主要推动者,NVIDIA提供了多个与体积渲染相关的技术和示例: + +**NVIDIA RTX技术演示**:NVIDIA的官方RTX演示包含多个体积渲染相关的展示,如带有体积雾和云的效果场景。这些演示虽然不一定是开源的,但展示了RTX硬件在体积渲染方面的能力。 + +**GVF(Grand Vehicle Framework)**:NVIDIA开源的车辆渲染框架中包含了一些体积渲染的实现细节,可以作为参考。 + +**Omniverse平台**:NVIDIA的Omniverse平台支持基于NanoVDB的体积渲染。虽然这不是直接的DXR示例,但提供了NanoVDB与GPU渲染结合的最佳实践。 + +### 5.3 社区开源项目 + +GitHub上存在一些开发者社区实现的DXR相关项目,虽然专门针对体积渲染的完整开源项目较少,但以下项目具有参考价值: + +**DXR-Projects**:一个收集DXR各种应用示例的仓库,包含反射、阴影、全局光照等效果的实现。 + +**WolvenKit**:一个开源的 Witcher 3 modding工具,其中包含对体积云效果的实现参考。 + +### 5.4 学术研究与论文 + +相关的学术研究也为DXR体积渲染提供了理论支持: + +光线步进与光线追踪的混合渲染技术已有大量研究论文,这些论文提供了体积渲染与表面光线追踪结合的算法基础。 + +基于物理的体积散射模型研究为体积渲染的着色计算提供了理论基础。 + +### 5.5 商业引擎支持情况 + +主流游戏引擎对DXR体积渲染的支持状况如下: + +**Unreal Engine 5**:UE5已全面支持DXR,包括体积雾、体积云等效果。Epic Games展示了使用DXR实现的高质量体积渲染效果。 + +**Unity HDRP**:Unity的High Definition Render Pipeline支持DXR和体积渲染。Unity的体积渲染实现可以作为理解体积渲染工程实践的参考。 + +这些商业引擎的实现虽然不开源,但其背后的技术原理和实现思路对开发自有DXR体积渲染系统具有重要参考价值。 + +## 六、可行性评估与建议 + +### 6.1 技术可行性评估 + +**DXR体积渲染的技术可行性:高** + +基于前述分析,使用DXR实现体积渲染是完全可行的。核心原因包括:DXR提供了足够的API灵活性来支持体积渲染所需的自定义着色器逻辑;硬件加速的光线追踪可以显著提升体积渲染中与场景几何体交互的性能;NVIDIA等厂商的硬件和软件栈已经验证了DXR体积渲染的可行性。 + +**Acceleration Structure与NanoVDB结合的技术可行性:高** + +两者结合的技术路径已经明确,多种实现方案都经过了理论验证。NVIDIA的Omniverse平台已经展示了类似的结合方案。这种结合可以产生高质量的体积渲染效果,同时保持与DXR生态的兼容性。 + +### 6.2 性能可行性评估 + +DXR体积渲染的性能表现取决于多种因素,包括硬件支持(RTX系列GPU具有专门的光线追踪硬件单元)、场景复杂度(加速结构构建和查询的开销)以及体积数据规模(NanoVDB的访问效率)。 + +在现代RTX GPU上,DXR体积渲染可以实现实时或接近实时的帧率。对于较旧的硬件或更复杂的场景,可能需要采用降采样、降噪或LOD策略来维持可交互的帧率。 + +### 6.3 开发成本评估 + +开发DXR体积渲染系统需要投入相当的开发资源: + +**学习曲线**:需要理解DXR API、Acceleration Structure原理、HLSL光线追踪着色器编写等专业知识。 + +**开发时间**:根据项目复杂度,从头构建一个功能完整的DXR体积渲染系统可能需要数月的工作量。 + +**维护成本**:需要跟进DXR API的演进和硬件驱动程序的更新。 + +### 6.4 建议的技术路线 + +基于本次调研,对于VolumeRender项目的DXR体积渲染实现,提出以下建议: + +**短期目标**:实现基础功能 + +- 首先在DXR框架下实现基本的体积渲染效果,使用简单的体积边界 +- 集成NanoVDB作为体数据源 +- 实现基本的体积光照和阴影计算 + +**中期目标**:优化与增强 + +- 实现基于Acceleration Structure的空间查询优化 +- 集成降噪算法提升画质 +- 优化加速结构更新策略支持动态场景 + +**长期目标**:完善与集成 + +- 实现完整的体积渲染效果链(云、雾、烟等) +- 与场景的DXR光线追踪效果(反射、全局光照)深度集成 +- 针对不同硬件平台进行性能调优 + +### 6.5 风险与挑战 + +需要注意的风险和挑战包括: + +**硬件兼容性**:DXR需要支持光线追踪的硬件(RTX系列或同等性能的AMD/Intel显卡)。对于较老的硬件或非RTX显卡,性能可能不理想。 + +**驱动稳定性**:DXR作为一个相对较新的API,驱动程序可能存在稳定性问题或兼容性问题。 + +**调试复杂性**:光线追踪着色器的调试比传统着色器更加复杂,需要借助专门的调试工具。 + +**生态系统变化**:DXR API和生态系统仍在快速发展中,需要持续跟进最新的技术发展。 + +## 七、结论 + +综合以上分析,DXR完全具备支持体积渲染的能力,并且与NanoVDB的结合在技术上是可行且有价值的。DXR体积渲染相对于传统Compute Shader Ray Marching在处理与场景几何体的交互时具有明显优势,但在完全自定义的体积效果实现上灵活性略低。 + +对于VolumeRender项目,建议采用混合渲染架构:利用DXR处理场景几何体的光线追踪效果,同时使用Compute Shader处理NanoVDB体积数据的渲染,两通过内联光线追踪或混合管道进行深度集成。这种方案可以在视觉效果和性能之间取得最佳平衡。 + +现有资源和示例虽不完全针对体积渲染,但提供了足够的技术基础来开发自定义的DXR体积渲染系统。建议在开发过程中参考Microsoft官方示例、NVIDIA技术文档以及商业引擎(如UE5)的实现思路。 \ No newline at end of file diff --git a/docs/plan/开题报告和任务书/任务书-王子文.docx b/docs/plan/开题报告和任务书/任务书-王子文.docx new file mode 100644 index 0000000000000000000000000000000000000000..1e22002876e437591b9ecd2b4b56cda3d7308d9d GIT binary patch literal 17641 zcmb8X19+v)(l#2~wllG9+qP}nwr$&d00t0Iv zgXSm|Zg123W^bOmxjERl+t^&+Xac%yWiKGa7&}2J z;B`e6+mPf%9*oTbwLsEVLKAE!*fEe2k8cQ`j)=4a)G6N&{R3#glAsW;V&A`-*Jcwi zc`#lGaF|P448_li=X?Jzjaif0@k-hNyru14eMHG)cF8YIOx#*1JYczcdOdPLobEUmQl zGF3I7s9ue$GH^GqkB0o5Fm=#^J>5yRRXuaVlDQ(rY8Yc4?m-P2Dy)0iGD1mo5SI}B z;yw9f?0RqmB(8;z2KTM2GT*2O1ZIY*q^H-3gBtiajj+o1UD z$|*XI>q<6`alaI5cVAgDR*5YbhqB8o_qy{6k`VCjFja(5v}R>yCm@xuZ*`oZP6ho8 z!J}dV``S~!03{sw#QF8naK~+DCV>`8X1CG)>n^T?kL*V_4C*)s#kRV^)@5INb~?^p zIBMA?+A7+m<`)8aF@By_YU$S9-8t*g&7PX5rRaE4?s#LnStKUf^~K~C$@Fa2jwTLn zyxm0~s#s80W?(WMx3Ag3t9gmN$g%Iif88+~B20S^SR4Xt!_P-(j;}15laEJiL}=tC zjd{-f0>_Gf?!yzf7u5@QG0O%_=2*zU95YLAO_i=O>bn@z13Evg;!bmVNA_Ef|GP;9 z{nVqIouly|=1}51m(&^>0H9VA0092qBu>sA)+SEB)!d~m<@jS1af7ShjsI?3SKc@Y zg@R!*6G385IX&@&kfo^>ta23tkQ@V_wSvn1#On#HJH`jz%*US=s9ey@&{WmfPq({z zd{QlscCiCLcb>$3Uj#GCnjx!)GaZy0S_H)mK5BL4wW^D)DZg4BtwGq>o5Abw;5_Wn z?`@!CN<)K(tP`e}Up2R6$FQ}w^3B?>2WExal{cW0UEKQ5rhNX2XNJSYaXLLzRi~Obwbtglv9T!VS=MqPmgwvL31w z!@mN_wu45;U9!_+T9PecGr!tKbH8BSq<@)uWbKHz5k@=+f$-1}l%5yn%4=k|nwpIB z3SEo!0>y2s%j%(%0rd9Ge{XtA$A98x-JqR=HOaWc057a5a!00vRz0Q{0#f%qIuOxO zCF(LpwYsoj%~H$i^hPxuwxP28S>*F%4xI^V;r?(!hzzRrB|bar`R1I**p#GSs@u>- zG3D08K`TA&Fy+OGw6PL~)vOw3&z+$oPD%Wb&KvoSToEj%gG0-2bbLpSovI4n1V;Dc zYU|_e%I}@D2RGG+`1NY*g6jRS?m%qQv!rLq0V@$%@m_WXLmk~kmBuuTOg?{>zx(Ai zrLtQHDs;(ke(%&lgR_%d3_enr&d z2H+E!OcgqP-snUVP9{oRYw7ISw!7xvBKA(c=*qDz;mMR zQt!&eYTp`#CXK{lPNVUevh%#9?|5Gug(COHVa9&NXTmY$GvzK7Q}s|I`axKzGw9CU z5q@Ltin!NsPBcusDiS@?5QPzEh|YjFKx@by=&Ev>K=K4Kl%Z1YsSBxKQn)KHlxHuV z3Me~;&hwpOpa{pso#96&g{w)Dj_bwEOeI2%rzr-`T{)A!mTRo;#A>kWOngPeKt8CN zh??UU^l+8>Nc>YEG;E=tpy=slaohnB=Dmdw^}_ajRO&(b;p?50Pm$>L{=4K~Q?!|Z zC9-b_suoJ9=9L)9&ES3aRG%&w4>XD`W0s4-VrmyzgVc3u4sh5+O%=xV=OQBYNY%Hg z(ABy(2T5f^NC?>Ll7f-#^|+sRAPRP|@n6o%sYai^uLR)~d1^OA$NBQ0ZMXpzNPtP0 zX9yr+na2mao~kRYS$tlxND6YmIDSk|t231vJ8faz@zx?`GwYEEUUuXs{-pIC#fT={ zleX-t0+(uHLio`b$b&+y2ksaIG~`8Fc(jej)nuWN44G0n0Bz4aeR^~FFy0`bh}1HK zr1<$tY#D+ptCBk78}Jr}D_*(uz++udd0>AKxI8rpk$vDwUGz+h8t3}nGce?v<*4QW zNQ`Chh0hu&Lria9ksl01Ye&oVhj`-T5<6LVx{dYw((dDxft&TR3a;e(_+zA48f)^8Ye7Ts48};suwOmaSfRn zrlZi=-qr}cr4hx7nid~qEir*_@TuA;MnVdyNl9ci2V@X28jJoodvHHIl6}L ztX)cz1pqA`Q~;!KQ0AA!L5)We`>)$LTHtQYK6l9^I%wI53eYlPRa@X|=CC5NAtp<_ zLZus{etZl^KQUrE=!V3w0O3P+nVmYob_V{OaC7pKCWBTvMcs&^TaLnS3rJd5V>wLf zru}2+kGX5I!#Gmo7x}`Yd0y;BN9iB2&&6>F9NFI@@RwEW+aAs%qSqcTq%2+)8AGvo zEPu3#uM8jf3p4xfuL3?z7JZe?s&z2=S^hE7p~Q~lmn`@TQ+w9lp*xkntWN48_<%fYNd91B(4-I zvzi>q=B8s=(lrgAGNcRY0i_7n<-G{u4#=O%NO_dax27nblxcF0eyRcsUp$6$Z1$L(uFf5j8t2gw1bCkqU;g zB!kiHh!ABvD@b@%%w1}UHAOv{61Q{Z}3Ts8l={*^V+o4plSfESxQ6q70TMjb>AsD37~YxYZpw;(GVu zY1P`rijMy;#tZk5>?qMiK709Joc_C)pMb$ENx^^B zB-8RKhyA3m)Y0Fv(Cx$>8Sypw|0lfPl6Y<|SW^B^r&NXQG1GnO(mJ7}HVVOy5-8pA zOc^G!%KQ!xNxvRQZ5o)?UMT9l71KT>vU><3cK;mRreuA!thqRuIa~nt!GOEOPWmc? z6A{DRsTp4UGe)ofFs8(R{rs-Q7!1sI?;~?EK@3|}gZL`}T);DE~ zZXeb5MQUm-wC`T;kSF)Trz=UPy{rD>)$?jM%G(N4%)T9)>fw?%y|j{5FkD&g(FnPg zkiEcLA96PKd#A!m>1x9b&q^0hQ5oKvr^ii(Z~0> zmc67Nhc*pz4#o8hs9fTV^nnbi<258Lw{lpSbFG-1v=LHwzmW*%4_Mlr^Yi}&8oT`~7(}EsuxZxl_ zjvCW(@yj<8>3pjXeuY+lONglUg0(#fu&dn%USvBxBNMBfFHoVgTCOE20#zl=2zsTX ztY~0TL>TCDUc4&VWH{Y4z?< zs4WWaL0~V@xOLB8PSWnZPZ;^RV(PZ>5<6~7!Es7u7rWi4Tr(Nd#c1^0C2thNVD(~A zb=24ob82Gymg@8LEe+x}Hv7;+P80v|2oZ%g+>IEr68iua_nMjfPJukHBuKD=icl|g z3!RAvK4d-+$a1iWVZpgzX`@F?93~F#zzz|`Jn1q?wMW(qusv-H()iR|<^*I&I(8T- zi@l^iEYj(#HX1EqYQd7wkh}JMp~T1%NhhYbxVo??EIpeLLIh{1l_|0BMtC4w7Wh|| zH!>{kxKNwNv$XfVn<4IUncB9l{nHKXKo=Q{5Xzkja5q;g-{yFdT{ z%3%Ip4gWQFcQSEywy-t(YieGirsb5yj^ewO@e3Yr6W57}T{;I&-+cayO{uI~o=Loo zP4J+2|Kjt#*Wi#Wt7Yo~uSRxOw^Q0y*N5)h7$CF+yO!p3h>Z+AmAk}uTMHkr(K2W& zB2+`t!t9+Am%({YzxyNnt2J@M5`JmfUXUaO73!KUMHl9*F~c}25<2%7O!_u$W%0hU z?^Bc{cv+sB*Oj7?))1tp>`pdZ^0Q;S+o)oKEwUgt)4XvpADaSt>{e5D-i+YSo3E#6?bYviGI z^(hDiP%k!W5DdteVn4=bDHhQYPBr`)u@VR$8^_Q(QRnxpjiFgQ&~o`0MDw8Wh#ljtuoNgh6;ML#@gu!*zh{&%B+-q~8Siw{qfyKz{>-d#vNp_0Bs=%8!sdnNKK3xJ7k~EecyHA07>`D`ULn;qR z_C+Y3%(sdw3S9`o+yCenOxX1+!R)b9FUYKg+Bz zx1r7-&s{wUxcjvMilZNJ(!J7&zb&K4s$70#7px=G7^hhuWRaH{Q;pG~Y(?vSShN}R(!vJ2+X$EJ#?U%m6K8PzCoXwNsh{TbA<^ES& z{j&D4Of#?UD@+dA`mfT_*+bk;Q=DnCtyo}dQr16v;m}3>fM(XDHG=h!ZFSV$#O~XhW z_`}t4-CZu%!`AwGB*&}uVgxLQU{c%d(it%%b^#%Orc#{G{c^~Ce!xocK8Q|aNfd#( zeL;>0BS57YF%Hsz*e}QcdG{#Wr3o`*!D1#JwU9aNf{Bq+tV;aqE9$1J=?N}UN7IIY zAVx*KC10-fi5egpzW%S3Up6)TE_}(uXE)|uMbIh!~#{PsfBsI33?$@<{e`_bQRexJ^+WjRF&SwQolnmq?b5sB#1M3o+X+T9_9AJf+6jiCJQNMDkO86k!U`PJA`W86j5cgjw7T3nwxMM{%m zjHz)iR9m*kufzUiT+n}WzF4*?8fE#E83vZ>YrZLoB-nU)3N8bwV2fr-beL=(BaWDZ za*u_4G%h%O;Gsf@y@4_2PY07_Ks{6h;#YvJi7 z2QFEVyU+O5oIcoM0g6{I;1B2_bynFz%hT=qjj9(mL!7Qu>8kLsV~)SiHzqL@E^mq^$JV*bGU;3pTm{$_i!yq zS-0J#M+m)ATXPHdhL_OPms*r>n63F*rThS>y%%48BVZJ?bKxcp$G>1B0c*A&* z%%*BZ)Lsi3L2!@2N@n&bh%@j`2_-y?DZcO$uohX(cH+cyerqB0D+P1Phm&#uakaN2 zF;c;dXdDl!yK1Pci*UHprFRkGE?m0CggoNKCJjVu9P*}NAsdSc!zH~sd^ol5kpsZ$ zIN^f51+XkycXz(wSrhDTrrugaCyx@%nVl5zm%ZXUQ2wbJ%i0vvAURo4LbJlL;u8$^kdZ~xzMoO z6^H9rQ~Gz7m-1MdFH{ikyJFV2@c(zm?x*wiZ^y2)xrvR*AMV|x0V{U^FaQ8*OaK7X ze-i#h{+D^Z(2%mjW<%&kKlW2U?@BQ~L&Qt~){6TYlLL~FNF-*Nwq`P@Ln}TWYb)SL z357x)kH*2wKPLq*G6w)Vo6mFCvltS@{0kA+u>_Su;U1V5M8p`s`G=h;@3egnp_*D9 zk94_Pcsl{L&2viJM0ePNe+Ws8=KF@gRS{J;8HuEjutucTI|}s2+Cvz=wulzvFyuoo zFRE7g!HA-%R!Jg+K1M{GMyS$PHbZU!Bw7z;C=O1b9!MISz=tT<{Yg3=;cj#mhCsqj03uFSpg zC07b0BtOibO@7@-t*c3yTbT+UU}+81mhmxlWC*Zt&N6r~QwOS6wOIO;UDp9B*Y19c zvF*~Ld$Rz50!p`-9=g+5x4Cq+WU2-n@8R@z!^)Y83}Jh-tF_;(sNjRH6KMZ9h3a0h z5<;Wt1Uq)xb# z!NO`fjZUr(J9Mf@C`z4jwyYV5N52W|52Q#UaXMxZDn{-<^!8FVqxbO;)+Se|UP*2a zO}yvIixQqfh&qc5NS0y!oM#G=8ym8aq*fP;-^1Gr6Hu7Lj;AxzT^A!9uJ)6E|6{>cRj?T z5pTla&W&icdN1(sG40+o^$+=mXlD2?7W;71WM3}f1jA~-+aznMT*@*cDC|0}#x{uj zWEH6pMwD&1TjXIK{?5?x8m#WYLjY(N7*p()=iU*{uEa<~TC>^>8 zQ3p>PqJ=$UiSz{UcW0aMzixke{WhFl~uvo_>~Gf*q+Z8EL)(y~5Ic43%cfR)j5JH$$apmH%@zeX+vJ*jn*0cqFlI@4*YfklsPaH&v4@Zf+-ZAV~|5oG&efiZB zU~*bnBMlh6r6d?YYVE;<)*JSuJVeY#qvXEBu3aj!g!J~<;4}unFj1cKyP9j~M4Wnh zK4(?RQ~!*pFn&h{-CEQ=d;NHhZ=32k#ZZr#HpTFrPC(-i+$7QZtPwKc5yRf{q!Rdb zgcfi}o~CL2g(vzBBJFu;mLZ_>RFy!lMDVUkG(D=I$n=3m$c606F5^->b+xpICaRt~ zj5Vn8q3AeGsP*N}N)9?)JS-jF6*&d-Xplzjt0c~*&hW?#P&d{tm2*wA>~=L-QHh#& z%9N(<^ybX9Z|G4`%UI{BEdiyainEJcme2Q7SkxH+CNzE^VQx>E#`UhjYcoVxeNpxN zw{HPG;f==Hqi{$Lx%M=i?N}tjhL;M7&E71(3SpR+unOB%Sosk)H5_H)Q`};3P&Q~8 z@nY-=rW&z{DHone$-Qe)r#sf(cJ)ohzQ|wt;^27*aqhSwP&a566(V6E0oJ)wdaw!s z(UC$EYE}1?3^OO`{H)2>6?$eb)QC349YXnuQ(MxRUsM-~gQ3>MAtV@+Jc+eKuL!#= zUAZI^Rh!_XzV0H&rkKGb>@>$jqoSa*P-CbX?18O5elV2T*=Lz+Xr5*oHdErI;h5!A zqqRncq637ayFWAMGBb++V;QB7#xmrt5}IN;L3>bhj5uvi z?_Mws?>bS17ApGFr)0YM9dY0-AOIHM-`#mz$KZqs}W<% zrEYQ{d2Jd5lle}tTQjHgTh~0?zO3?uAd?p~OVLnhX@(YMzQHBD*?y;DjqGMLsWGF;=rp_D+R^X#Ok+B#i$# z*4zT}u^S%kPalufc=+O1;A-;VVsq+PyD@moV>p(y(&1NTlSQB#3?K{f?m@;zK$}z$ z=RWxn#_J;jp|C2w4eUT5>|>FGH!e`N+~k&bekkKo!}uyNkBEdtr&LHb<3${l;?Yu6 z1{F-yFIg0*qMknYo;Oo6&Vnpi=2PhYIw`enXMmcYq55EVbtA{+g%i`#_A1sKbQ`S8k1G*sr_57QECD`H!yvK% zH->SBhDULwUiLZTZ}9J7WX7XZRKLGkdbhptE)mm0;Xl=>fqB*pIm|C8MNA#uc9UMo zrzpozg-ZD5LF*(PZsnMPD75n>O+#W(pO~(?bA*u_DM2n2lmgKNXo(_;{lNDwU{i#@ zt{*&q(?{KvVb2m};(HxIh(^XC(KZ6F860|irK;>0MO1G~#<;L~O>$DdxOBS{=|Q9w zH%FyXH>XsMGPwUi8(~Hkw^j;@`m1dvawfM<0x>Rkv}aBCFEZjx&eSRx{wadK$AtGg zO;JH%2nWJ=&hiNzDnJWrc`NzIQX=5Qv}^W4Ivdy$E7#t-trp+Ns;l#%2@KM~mkOP7 z4Zcej>qmVWEere@KZsIGFvN)>s@Yu|Oum-LudW&w{a%%rFdO_HCl@blZ994vz6}uy zL18h{p`}VhD2D2b9@r@8ig*Ja?UBH09`5mipR$c7Hgz)FG$UYe2tBtL1)_rb2)+Cvs8f5jxvPRMSONgZ;1zfD>-QS91%x z_#$qQyJHb3T<;bJv*jvOv}Pk4Y1g6AeNk#8g*@sHHULlc$hqz^(TY70>Kj$0B;rGs)%Ae7C`%zM2C)ut7gDa4f6J2=kPuk@)kOM&6n z`b~HI1sDvieOvHU$tb+`OOKS>jf(I^Yc5ZXG(jpfDJiEU*dkj%C11g9C&Tw=x7Xx38D8YJ(t@IvoJ2@+W7j^N(~q zO(r866{`F0Q`}8zrczCE4~4c`rgvwQUG9FrPGBmSogE(UC@|VOv@&El5r_6v3XyL^ z4Jn5uNCB2#l7F2#oQxevE`l;{Mo~dOOwC-hNW7l9j4v?8OR?yoLspmulTrm|u&3QY zPDr|S^bvHoTxy;D3Xn;geV1p2KsR$wkn!xlej73ke_qF>8YHFe@jS2AwxSvIvD!$P z_BvUaFGP@uOc=!9)Wn~=MeaPKX(0MIjE_lV0+{d zKyNwlebHsSXjIFhd0ti1b0M(4?(XMntGB2ZYNfFTQ83(-AZ*9(|56h@4mu_1=`wOO zw(LUaY=UmbZ(xxM+SN-RZFbm9aQ5I2y6zc9ycd+(c_9!a533`(J-mM!`iqQt3ffzm z2x=a_`!0yi$M;ZZ^0eM&V`!*IkQ?zQ>_OL#S$2iQ>n3u2^vad@o`NJEAsl1p^E+~0 z-f94i1`y3`;h>o7Kz0@N)_EikczVB7HG~#P96&3~H>*__fQQ6nv>xZn8fR`QZ&4F) zQ&8-v1q9D?JLMn9B6Haa6tr7+n5c;{HCTQjYS>(mCAj|1Cb;GLc?uTN39U9&$)E}Y z4v>6BQ@IdXnNXn+WV8M8p#vGY&X+VTxp?M-S@ST63|KP463yjuOi#=~a!hX=7NOtL4aw7gk>SF#wjc1Iy`Qz0=MmC>67{LZXiP+Md_2#a@`25y#o!vAwm&o zLcW@loUa#o8O2R+IMlj7z7&Z>Y{h79r@JSHSdX}W_vY*?Lw5C--Nr-=3xB4VIg9Hv zzxLConY(y{yOp!cBS;NaC+c^xrgojnBt!Dn>BNdk%34RCUXQBF!l09Pn@Kv{d*;ZQo3zrA{3mR)B#(uJbT4L-(bcq6l5VsCxcggFYS zR#a)A34R9eSgz|3*BEGY|K@zBj@*(pj}lu!G{!v2y%z7#{gqoo+xNwb;!H}ZE~i~8 zzG(CL*2L%Kl&vIEEHU9PAnW8PRUE! zS|1%>FJ!1tsuKLvWjbBwZeNov4?#;XI|6)h{Gsjmk-!ppdsUq5deDkr@Ds==INQmA z^rsCkZ|~%-M@Jls{6BCXo+-*{tLYQHwhMVaq%7XS#9MdAi5E4!E&bPF$lLCIMgH0r zcwU-0a6^x>YAZOAS9Q2&SX}6CJ)i6jHp_0eyEr=920k|kvsOFCRoW6dY@Jt2I;hCY zCW9wjB1BQK7>)LMH*t8z^nl8QlvsSAYKJr-VmBw3oNh*8QOne$?SAg>egb_KE{?r4P$}T8lbshxLVs{%HnCs^ zV1KV4Dx&qh@2b<&AkQzFahb;Z3==4OAT}RPSNYp@F9(xKkdeg&S}`1P7YN-?BJ=xF zrw<&guAg-Pz6Wh)7cHpAz(ZLk+bl`FYl_nsHLqi=La+e~uG#DEp}C&=NEM1H z5E&+}UwHLP^}Zu7u;wR<^*e)ZZV~R|ymBzl4!76{*YxF@h+=JrkLK%X#_hfay^kbQ zR85Kf#FG8TY#1E8Pp_{<6Y%+01nSVHZ1m?4Zb@@X(QW0GU&zle-woKCn+R73*m?Dl z-=_Oq-xJ`$oaa;Dii{>5PUZWQt6}cr@Wxw!UdtgsRdwkt$|Y%QWaRCixLJy^?cY&x z=Al2mx3M9mp)^JDjZmS2eID0~1|rLWVvE&4d5+t-`A(2?P6L*${IVu|4>vb>lt^5{ zxD5N*kY>__Noy25Vz5|_yhWvxJ}B0k#t#bIzYsstcq1Vh4ds$5Iuc@ciD7V&d%Hxf z#YvY!;j2}T)URae=NVe@)crGfE&1ff`UWB^tU#IXP;k7>)BVYwa#gm4tx@?g@&G#Y zWE8~ixU=WES?AD9F>LXN8t@%Jm;|}fchm{!Nyj>Vjf_m<8HIAm`rMubJOx0EMkq_p zp$N6c<2;+`juAEl84t}Wpi|b?bEbwry#FK+N4q6KRg03D#H|?r=&umY!eT}a7E-Hx z-Q;9WDEx%RRbKLbX?DWK%_+)m_wPnG1bAidgdbWt@fC3u#_%pAN_IY9-rM+x@m6za zU2K#=M?U2#MKljT_I zIq1kx0o>sl$UMB0JG8)`Cq*b;Q*0`T40)`g)V5ErZyN`U!vL{P1av`ptWw~-)ITOt zlC!v21rxgn{|uBEd{+d&Mi8=EMF;pQ1TqX10EJaptnr;&1RX&qI?Iw3eA4v4R@ z$)I$O4hhNo$`-rA=J5D^(B$;{GBAgI(0qMnkh_Oe9r0S_poElXi;NQqUPO~&_+!qY ztz#zUwpy5p%vkv%J?g3$tl1pVblVS1{g zZ`WR@yFQ<$f4&$5v+%HuR%O^uhx`eY0F7xuyCI{b!z-;}|R`u3<1POy=MNzbyb%{*Z|6Xx5KwgL5oBA2-akZwlP$p@yCk)BQ`9%lQS3>A|>=vGguieWikzDW><1S*OU8VI}p^xxJG6tYD_ zI65+_D!P}0zrJAvgmdfYCPn@b}qxmhHf)NL5%Wn7gXF)#gkRb_qD5uRm-y( z2tD8z6<@Z7-_tkdp0DpH^Ueap4O?=D!J{>ZutEb#^ht;!XoAV?X*d2QR{buqr<}qP zxT=(h@1l8`m+%$6#R+}dsu1ZmF3?hwmCJu%0rC1yJ_IP&7xIr8r?Gx2ZjP~#vg z`0)^1a;Gc!5Mdh5SL%Ql6_vGVfFVKUc*#G29b~KhFUL^jcZzvaEiJ}pF>19mn)v_xH~;KzajRaa}02QEZuog%p!nz{|Mc0^jvV8v04scNgUV5B#IRq*yPJ5`f9krbbEIWgv1>n-|>QxdT$=gtqBn9y}$=^*(fSH{^QY{ z_JnnJ#2~<_QK1AGjGYk7D~ZG)vA(77Sd|l-Z!v8Z@xK~SFcqMdCmqk?491Ua-|VLl zi!x9oVIqOmqs`3rE!60Lh#f{8)DAR0BoU$`Jv#Q_{YFpiK*}|Z0n5F`JF~Oc4h~~`JlFplaV$gYG zUh?S$@-;1*w3Mp7Xn7$1qc8D=;^c!2#-7U?@ba^e?@}xVeC!nR1fQu zMw`{`MHqCbtg)g82x99;=qK=F!_Wo9b-}3AB+)c=lxou?k*{YXK|8CpE!KGqL?C5t z2`-;E_Y!mtDD$9!0^|hc4gSLK91kKBu(MK-U#d*;YRDzX4FnM=mO6t#0U!jFN^YA| zi@5ul1;>m%tEgQ(+pI8CNL?8;# zL)1~bRINaTD5GK2q-hDICGyoIM%-T3E0L9+h{a;z7}&l@fz)#0=#mm}r>hVtUOtF^ zO@Y)IO;;7tX4WQ2^6lvs7s(tLj??SCLh>9B^Fx&kFX=52g?RuBIvd?g-VTsWM#4lX zvL-?`k_P%_zKhq|a`je>C3JJXCpy!ydu^u1bh#`4+79__;is8J@)v_du#M2()yB#1 z&=^fM%m;-sbxTvA6GR2c%@s7QmA+Hb{7+H4o;G^sSYwp1ANta<73XV^EGf;LYmJg7>pwKpk?W#?8RPmzuQN-BPYT zRAnpmkBv4c(Kw4v_Owbin9&5ZDU>EYbZC^0Zndz*zQ7mlLAmrpL{geddAO^#RwZry z-@_?BgCzj;98IkM%o_$IBEtXm`Pzak?1USB zk?s3=Y2W}&#N-(ybX~kHjLAB6F!T}uw$GUCh22C>%S&~fv6qvq@wiW~Mwm#K!%7mS zJ-#>=?iq(WrlPYodba?anNao}3)I4@R^VK=!TNojtGQ;$8UL;?;V1&tv6_53ozoDs zju6v=7rZJE#xc{>g?H*IO;Rix46_6-0*xUh8)-f9oK4=qgL>v!hXK5q8{gdfO_|%- z_%?Ks8)=wb%=tb~_$8j>t4A*U6nY|#&*UNO|6P**6PWV9iPMrDtorR!jOCvu7U%Q& zSIFPrg#W$Q_?LWJl4c|a=@Evn0X@Y7b0S#FGTGr-CQzT4BO5U9c)S=RMgXk*CmKiZXpK737%Y*d#GCx z;b93(nByhgdv$%u#q4@0qYjWJFCxCBN&7Souc!hJ_S2a~5m8JqBg9<`+1J3qQpNY9BpQH45Vy>3Z=O5DNwyd7AhrNlD&hOpXq2vkM&m?J)&%|8# zgf!k-FP1Cx*41rg1zIb z+ILO4;=Pt?%C4zVX(vXW#7HD2&?;Qe?drghH^;Yz>^fe(!BsSehO+y1CBi)5Mf6U1 z)K|&07$V%TOeZP6N=)%Vx>uT(W{}h+C@h2K?(ij=i^<&8?jCz2{4qrB>p0QX+T>Sf zl2nFejuufolHW*;wO6zIJPvLmZ6H=9!nyQ-TU};wWXhq$zfjI5FA6CG{{cpqbXQO|br{9>r8`b+C z%wG@F|660fk4^Zy{BG=b`L9D1{>kK@$0+%=k}D;)MU|!hhHCC;ZPD?SJ5M?EixQV}AQ5 z{?91w|KK}5Lks_m+5SJ!e+13`2W^S*5A$3F# literal 0 HcmV?d00001 diff --git a/docs/plan/开题报告和任务书/完整开题报告.md b/docs/plan/开题报告和任务书/完整开题报告.md new file mode 100644 index 0000000..849bd50 --- /dev/null +++ b/docs/plan/开题报告和任务书/完整开题报告.md @@ -0,0 +1,131 @@ +题 目 基于DirectX 12的NanoVDB体积特效实时渲染引擎 +英文题目 Real-time Rendering Engine for NanoVDB Volume Effects Based on DirectX 12 + +学生姓名 王子文 学号 2022302111081 +所在学院 计算机学院 专业 计算机科学与技术 +指导教师 肖春霞 职称 教授 + +课题简介 + +本课题研究基于DirectX 12图形API的NanoVDB稀疏体积数据实时渲染技术,旨在实现一个完整的体积特效渲染引擎。课题主要内容包括:搭建DirectX 12基础渲染框架;实现VDB文件的解析与GPU数据传输;设计基于Compute Shader的Ray Marching体积渲染算法,利用NanoVDB的空域跳过优化提升性能;集成DXR光线追踪技术实现体积阴影效果。研究方法采用文献调研、实验对比与迭代开发相结合的方式。预期成果为一个可交互的体积渲染引擎,能够实时加载并渲染VDB格式的体积数据,支持自由漫游相机和动态光照调节功能。该研究将NanoVDB数据格式与DirectX 12技术相结合,探索体积特效在游戏、VR/AR等实时应用场景中的技术实现方案。 + +一、选题目的和意义 + +1.1 选题背景 +随着游戏画质要求的不断提升以及虚拟现实、增强现实技术的快速发展,体积特效已经成为构建逼真虚拟世界不可或缺的核心元素。无论是电影中震撼的爆炸场景、游戏里弥漫的硝烟废墟,还是实时渲染中飘动的云层和雾气,这些效果的实现都离不开体积渲染技术的支撑。与传统的基于表面的渲染不同,体积渲染需要处理光线在介质内部的吸收、散射和自发光等复杂物理过程,其技术难度和计算开销都要高出数个量级。 +在工业界,OpenVDB已经成为存储和处理稀疏体积数据的标准格式而被广泛采用。然而,传统的高质量体积渲染严重依赖蒙特卡洛路径追踪等离线渲染技术,计算一帧往往需要数分钟甚至数小时,完全无法满足实时交互的需求。近年来,NVIDIA推出的NanoVDB通过线性化树结构大幅优化了GPU访问性能,使得稀疏体积数据在实时环境中的应用成为可能。但目前NanoVDB的官方支持主要面向CUDA生态,在Windows平台主流的DirectX 12环境下,缺乏成熟的开源实现方案,这正是本课题的研究切入点。 + +1.2 核心问题 + +本课题旨在实现NanoVDB稀疏体积数据在DirectX 12环境下的实时渲染,主要面临以下三个核心问题: + +(1)NanoVDB数据结构的DirectX 12适配。NanoVDB采用线性化树结构优化GPU访问,但其设计主要面向CUDA生态。在DirectX 12环境下,需要重新设计资源管理方案,实现VDB文件的解析加载和GPU数据传输,同时保持NanoVDB原本的内存访问效率。 + +(2)体积渲染的性能与质量平衡。体积渲染需要在光线路径上进行密集采样计算,传统的Ray Marching算法计算量极大。如何利用NanoVDB的稀疏特性实现空域跳过,仅对含有效数据的区域进行采样,是实现实时渲染的关键技术难点。另外,体积介质中的光线传输涉及吸收、散射和自发光三种基本光学现象,其中散射的各向异性特性需要通过相位函数正确模拟。如何在保证实时性的前提下实现物理准确的着色模型,是渲染质量的核心保障。 + +(3)渲染引擎架构设计。一个完整的体积渲染引擎涉及窗口管理、图形初始化、资源调度、渲染管线、交互系统等多个模块。如何设计合理的分层架构,使各模块职责清晰、接口明确,便于后续的功能扩展和维护,是工程实现的重要问题。 + +1.3 解决思路 + +首先,在数据层面,深入分析NanoVDB的内存布局结构,设计适配DirectX 12的资源管理方案。通过研究VDB文件的存储格式,实现CPU端解析到GPU端数据结构的高效转换,构建可直接用于渲染的NanoVDB访问接口。 + +其次,在算法层面,以体积渲染方程为理论基础,在Compute Shader中实现Ray Marching体积光线投射算法。利用NanoVDB的内部索引结构实现空域跳过优化,在保证渲染质量的前提下大幅减少无效采样。着色模型方面,正确实现吸收、散射和自发光三种光学现象,其中散射采用Henyey-Greenstein相位函数处理各向异性散射效果。 + +最后,在扩展层面,集成DXR光线追踪技术实现体积阴影和场景遮挡计算。通过构建加速结构,利用硬件加速的光线追踪计算体积中的光照衰减,提升渲染效果的物理真实性和视觉表现力。 + +1.4 选题意义 + +本选题的意义在于:将NanoVDB稀疏体积数据与DirectX 12图形API相结合,探索实时体积渲染的技术实现方案,为体积特效在游戏、VR/AR等交互式场景中的应用提供技术参考;同时,通过完整的工程实践,加深对体积渲染核心算法的理解,提升图形编程能力。 + +二、国内外研究现状和发展趋势 + +2.1 体积渲染技术发展现状 + +体积渲染技术在计算机图形学领域有着悠久的历史,早在上世纪八十年代,Kajiya提出的渲染方程就为体积光照传输奠定了理论基础。进入二十一世纪后,随着GPU计算能力的飞速提升,实时体积渲染逐渐从理论走向实践。目前主流的实时体积渲染方案主要包括Ray Marching和体光线投射两类技术路线,前者通过在光线上进行固定步长采样来累积体积属性,后者则通过求交体积边界盒来优化采样区域。两种方案各有优劣,Ray Marching实现简单但计算量大,体光线投射效率高但需要额外的数据结构支持。 +在体积数据格式方面,OpenVDB自2012年由DreamWorks Animation开源以来,已经成为电影工业的事实标准。OpenVDB采用分级稀疏数据结构,可以高效地存储烟雾、火焰、云层等体积效果,但其在GPU上的访问效率较低。NVIDIA在2021年推出了NanoVDB,通过线性化树结构消除了指针依赖,大幅提升了GPU访问性能,成为实时渲染场景的理想选择。然而,NanoVDB官方主要提供CUDA接口,在DirectX 12和Vulkan等通用GPU API上的支持相对薄弱。 + +2.2 DirectX 12与光线追踪技术 + +DirectX 12是微软推出的新一代图形API,相比前代DirectX 11,它提供了更底层的GPU控制能力,允许开发者直接管理GPU资源分配和命令调度,从而最大化利用现代显卡的计算潜力。DirectX 12 Ultimate进一步引入了DXR(DirectX Raytracing)技术,使得实时光线追踪成为可能。DXR通过硬件加速的加速结构(Acceleration Structure)实现了高效的空间查询,已经在游戏和渲染领域得到广泛应用。 +在体积渲染领域,DXR的价值主要体现在两个方面。其一是加速体积与场景几何体的交互计算,如体积阴影、遮挡剔除等传统上需要额外处理的效果可以通过光线追踪自然地实现。其二是内联光线追踪(Inline Raytracing)功能的引入,使得在Compute Shader中调用TraceRay成为可能,为混合渲染架构提供了技术基础。UE5和Unity HDRP已经展示了DXR与体积渲染结合的潜力,但相关的开源实现仍然匮乏。 + +2.3 发展趋势 + +展望未来,体积渲染技术的发展趋势主要指向以下几个方向。首先是混合渲染架构的成熟,即结合光栅化、计算着色器和光线追踪各自的优势,在不同渲染阶段使用最适合的技术方案。其次是神经渲染技术与传统体积渲染的融合,NVIDIA提出的神经材质概念已经被拓展到体积领域,通过神经网络近似复杂的体积光照传输过程。第三是标准化和开放化的推进,随着更多开源项目的涌现,体积渲染技术的门槛将持续降低。 + +三、研究内容、研究方法、技术路线及可行性分析 + +3.1 研究内容 + +本课题的研究内容可以划分为五个主要模块。第一模块是DirectX 12基础框架的搭建,包括Win32窗口系统的实现、DirectX 12设备的初始化、命令队列和描述符堆的管理,以及基础渲染管线的建立。这一模块是整个系统的基础,需要确保GPU资源能够正确分配和调度。 +第二模块是NanoVDB数据管线的设计与实现。具体包括VDB文件的解析与加载、CPU到GPU的高效数据传输机制,以及在Compute Shader中访问NanoVDB数据的采样器实现。由于NanoVDB的数据结构较为复杂,需要深入理解其内存布局才能实现高效的GPU访问。 +第三模块是体积渲染核心算法的实现。核心是以体积渲染方程为背景,基于Compute Shader的Ray Marching算法,包括光线与体积包围盒的求交、基于NanoVDB的空域跳过优化、步进采样策略,以及物理着色模型的实现。物理着色模型需要正确处理吸收、散射和自发光三种光学现象,其中散射部分还要考虑相位函数的影响。 +第四模块是DXR光线追踪技术的集成。这一模块作为可选扩展,主要实现体积阴影的计算和场景遮挡查询。通过构建加速结构,可以利用硬件加速的光线追踪来计算体积中的光照衰减,使渲染效果更加真实。 +第五模块是交互系统的设计与实现,包括自由漫游相机的控制(支持WASD移动和鼠标视角调节)、动态光源的管理(支持位置、颜色、强度调节),以及基本的画面参数调整功能。这一模块决定了用户能否直观地体验渲染效果,是系统实用性的重要保障。 + +3.2 研究方法 + +本课题采用的研究方法主要包括文献研究法、实验对比法和迭代开发法三种。文献研究法贯穿整个研究过程,需要系统性地研读NanoVDB官方文档、DirectX 12编程指南、DXR技术规范,以及计算机图形学领域的经典论文,特别是体积渲染和光线追踪相关的资料。通过文献研究,可以充分了解现有技术的优缺点,为系统设计提供理论支撑。 +实验对比法主要用于评估不同实现方案的性能和画质差异。例如,在Ray Marching中,步长的大小直接影响渲染质量和运行速度,需要通过实验找到合理的平衡点。又如,空域跳过策略的设计也需要通过对照实验来验证其有效性。实验对比的方法可以避免主观臆断,使设计决策更加科学。 +迭代开发法是本课题的主要开发模式。由于渲染引擎涉及多个相互依赖的模块,不可能一次性完成所有设计,因此采用快速原型、迭代完善的方式进行开发。首先实现一个最小可用的版本,验证核心技术路线可行后再逐步添加新功能。这种开发方式可以及早发现问题并调整方向,降低开发风险。 + +3.3 技术路线 + +整个课题的技术路线可以分为六个阶段推进。第一阶段是准备阶段,时间安排在第一周到第二周,主要完成文献调研、需求分析和系统架构设计,输出物是一份详细的设计文档,明确各模块的接口和数据流。 +第二阶段是基础框架开发,时间安排在第三周到第四周。这一阶段的目标是搭建起DirectX 12的运行环境和最基本的渲染管线。具体的交付物是一个可以正常显示窗口并完成清屏渲染的最小系统。这一阶段的难点在于理解DirectX 12的资源模型和命令提交机制。 +第三阶段是数据管线开发,时间安排在第五周到第六周。这一阶段要实现VDB文件的加载器和GPU数据传输机制。由于NanoVDB的数据结构较为复杂,需要仔细研究其存储格式,设计合理的数据转换和传输流程。交付物是能够成功加载标准VDB文件并在GPU端访问的测试程序。 +第四阶段是渲染核心开发,时间安排在第七周到第十周。这是整个课题最核心的部分,需要实现完整的Ray Marching渲染管线。包括光线与体积的求交算法、基于NanoVDB的空域跳过优化、不同类型光源的照度计算,以及最终的体积累积逻辑。这一阶段的交付物是一个能够渲染基本体积效果的完整渲染管线。 +第五阶段是交互系统开发,时间安排在第十一周到第十二周。在渲染管线的基础上添加相机控制、光照调节和参数UI等交互功能。这一阶段的重点是用户体验的优化,要确保操作流畅、反馈及时。 +第六阶段是优化收尾,时间安排在第十三周到第十六周。主要进行性能优化、功能完善和测试验收,最后撰写毕业设计说明书。性能优化可能包括分辨率缩放、降采样、混合精度等技术手段,需要根据实际情况灵活选择。 + +3.4 可行性分析 + +本课题在技术上可行。从硬件条件来看,实验室配备的RTX系列显卡完全支持DirectX 12和DXR的全部功能,可以满足开发需求。从软件基础来看,NanoVDB已经开源并提供了详细的文档,DirectX 12的编程接口也有丰富的教程和参考代码可供学习。从理论基础来看,体积渲染的核心算法已经有成熟的理论支撑,Ray Marching的实现也有大量开源项目可供参考。 + +四、项目特色与创新点 + +4.1 跨平台技术迁移 + +本课题的首要特色在于将NanoVDB在DirectX 12环境中实现实时渲染。NanoVDB虽然在NVIDIA的推动下逐渐成为行业标准,但其官方实现主要面向CUDA编程模型,在DirectX 12环境下的适配工作需要开发者自行完成。本课题将深入研究NanoVDB的内存布局,设计适配DirectX 12的资源管理方案,实现GPU端的高效数据访问。这一工作本身具有一定的技术创新性,可以为后续研究者提供参考。 + +4.2 分层架构设计 + +在系统架构层面,本课题采用分层设计思想,将整个引擎划分为应用层、引擎层、渲染层和数据层四个层次。应用层负责用户交互和业务逻辑,引擎层提供窗口管理、资源调度等通用功能,渲染层专注于图形管线的实现,数据层处理文件解析和数据传输。这种分层架构的好处是各层职责明确,便于独立开发和测试,同时也为后续的功能扩展留出了空间。渲染层还实现了后端抽象,可以支持Compute Shader和DXR两种不同的渲染方案。 + +4.3 混合渲染思路 + +在渲染技术上,本课题尝试结合Compute Shader和DXR的混合渲染思路。Compute Shader负责体积数据的采样和累积,这是其擅长的计算密集型任务;DXR则用于体积阴影和场景遮挡的计算,利用硬件加速提升查询效率。这种混合方案可以在保证渲染质量的同时提升整体性能,是未来渲染引擎发展的主流方向。 + +4.4 完整的工程实现 + +本课题的目标是一个完整可用的工程系统,而非单纯的算法验证。这意味着不仅需要关注渲染效果的优劣,还要考虑代码的组织结构、模块的接口设计、错误处理机制、参数的可配置性和用户交互体验等工程实践问题。交付的代码将遵循良好的编码规范,关键模块配有详细注释,可以作为学习渲染引擎开发的参考资料。 + +五、进度安排 + +第1-2周: 国内外文献调研,明确需求,完成系统架构设计,撰写开题报告。 +第3-4周: 搭建DirectX 12开发环境,实现Win32窗口系统和基础渲染管线。 +第5-6周: 研究NanoVDB数据结构,实现VDB文件加载器和GPU数据传输模块。 +第7-8周: 实现Compute Shader Ray Marching核心算法,完成基础体积渲染功能。 +第9-10周: 优化渲染管线,实现空域跳过和物理着色模型,完善渲染质量。 +第11-12周: 开发交互系统,实现自由相机漫游和动态光照控制功能。 +第13-14周: 性能调优和测试,完善功能,撰写毕业设计说明书初稿。 +第15-16周: 论文修改定稿,准备答辩演示,进行项目验收。 + +六、主要参考文献 + +\[1] Museth K. NanoVDB: A GPU-Friendly and Portable VDB Data Structure for Real-Time Rendering and Simulation\[J]. ACM Transactions on Graphics, 2021, 40(4): 1-16. + +\[2] NVIDIA. Accelerating OpenVDB on GPUs with NanoVDB\[EB/OL]. NVIDIA Developer Blog, 2021. + +\[3] Microsoft. DirectX 12 Graphics Programming Guide\[EB/OL]. Microsoft Docs, 2024. + +\[4] Microsoft. DirectX Raytracing (DXR) Technical Specification\[EB/OL]. Microsoft Docs, 2024. + +\[5] Kajiya J F. The Rendering Equation\[J]. Computer Graphics, 1986, 20(4): 143-150. + +\[6] Max N. Efficient Light Propagation for Multiple Anisotropic Scattering in Semi-Transparent Media\[J]. Journal of Graphics Tools, 1995, 2(3): 21-32. + +\[7] Wihlidal C. Optimizing the Graphics Pipeline with Compute\[C]//Game Developers Conference 2019, 2019. + +\[8] Clarberg P, Hasselgren T, Toth R, et al. Real-time Neural Appearance Models\[C]//SIGGRAPH 2023, 2023. + diff --git a/docs/plan/开题报告和任务书/开题报告-王子文.doc b/docs/plan/开题报告和任务书/开题报告-王子文.doc new file mode 100644 index 0000000..2bde955 --- /dev/null +++ b/docs/plan/开题报告和任务书/开题报告-王子文.doc @@ -0,0 +1,3 @@ + + +武汉大学本科毕业设计(论文)开题报告题 目基于DirectX 12的NanoVDB体积渲染引擎设计与实现学生姓名王子文学号2022302111081所在学院计算机学院专业计算机科学与技术指导教师肖春霞职称教授一、选题目的和意义1.1 选题背景随着游戏画质要求的不断提升以及虚拟现实、增强现实技术的快速发展,体积特效已经成为构建逼真虚拟世界不可或缺的核心元素。无论是电影中震撼的爆炸场景、游戏里弥漫的硝烟废墟,还是实时渲染中飘动的云层和雾气,这些效果的实现都离不开体积渲染技术的支撑。与传统的基于表面的渲染不同,体积渲染需要处理光线在介质内部的吸收、散射和自发光等复杂物理过程,其技术难度和计算开销都要高出数个量级。在工业界,OpenVDB已经成为存储和处理稀疏体积数据的标准格式而被广泛采用。然而,传统的高质量体积渲染严重依赖蒙特卡洛路径追踪等离线渲染技术,计算一帧往往需要数分钟甚至数小时,完全无法满足实时交互的需求。近年来,NVIDIA推出的NanoVDB通过线性化树结构大幅优化了GPU访问性能,使得稀疏体积数据在实时环境中的应用成为可能。但目前NanoVDB的官方支持主要面向CUDA生态,在Windows平台主流的DirectX 12环境下,缺乏成熟的开源实现方案,这正是本课题的研究切入点。1.2 核心问题本课题旨在实现NanoVDB稀疏体积数据在DirectX 12环境下的实时渲染,主要面临以下三个核心问题:(1)NanoVDB数据结构的DirectX 12适配。NanoVDB采用线性化树结构优化GPU访问,但其设计主要面向CUDA生态。在DirectX 12环境下,需要重新设计资源管理方案,实现VDB文件的解析加载和GPU数据传输,同时保持NanoVDB原本的内存访问效率。(2)体积渲染的性能与质量平衡。体积渲染需要在光线路径上进行密集采样计算,传统的Ray Marching算法计算量极大。如何利用NanoVDB的稀疏特性实现空域跳过,仅对含有效数据的区域进行采样,是实现实时渲染的关键技术难点。另外,体积介质中的光线传输涉及吸收、散射和自发光三种基本光学现象,其中散射的各向异性特性需要通过相位函数正确模拟。如何在保证实时性的前提下实现物理准确的着色模型,是渲染质量的核心保障。(3)渲染引擎架构设计。一个完整的体积渲染引擎涉及窗口管理、图形初始化、资源调度、渲染管线、交互系统等多个模块。如何设计合理的分层架构,使各模块职责清晰、接口明确,便于后续的功能扩展和维护,是工程实现的重要问题。1.3 解决思路首先,在数据层面,深入分析NanoVDB的内存布局结构,设计适配DirectX 12的资源管理方案。通过研究VDB文件的存储格式,实现CPU端解析到GPU端数据结构的高效转换,构建可直接用于渲染的NanoVDB访问接口。其次,在算法层面,以体积渲染方程为理论基础,在Compute Shader中实现Ray Marching体积光线投射算法。利用NanoVDB的内部索引结构实现空域跳过优化,在保证渲染质量的前提下大幅减少无效采样。着色模型方面,正确实现吸收、散射和自发光三种光学现象,其中散射采用Henyey-Greenstein相位函数处理各向异性散射效果。最后,在扩展层面,集成DXR光线追踪技术实现体积阴影和场景遮挡计算。通过构建加速结构,利用硬件加速的光线追踪计算体积中的光照衰减,提升渲染效果的物理真实性和视觉表现力。1.4 选题意义本选题的意义在于:将NanoVDB稀疏体积数据与DirectX 12图形API相结合,探索实时体积渲染的技术实现方案,为体积特效在游戏、VR/AR等交互式场景中的应用提供技术参考;同时,通过完整的工程实践,加深对体积渲染核心算法的理解,提升图形编程能力。二、国内外研究现状和发展趋势2.1 体积渲染技术发展现状体积渲染技术在计算机图形学领域有着悠久的历史,早在上世纪八十年代,Kajiya提出的渲染方程就为体积光照传输奠定了理论基础。进入二十一世纪后,随着GPU计算能力的飞速提升,实时体积渲染逐渐从理论走向实践。目前主流的实时体积渲染方案主要包括Ray Marching和体光线投射两类技术路线,前者通过在光线上进行固定步长采样来累积体积属性,后者则通过求交体积边界盒来优化采样区域。两种方案各有优劣,Ray Marching实现简单但计算量大,体光线投射效率高但需要额外的数据结构支持。在体积数据格式方面,OpenVDB自2012年由DreamWorks Animation开源以来,已经成为电影工业的事实标准。OpenVDB采用分级稀疏数据结构,可以高效地存储烟雾、火焰、云层等体积效果,但其在GPU上的访问效率较低。NVIDIA在2021年推出了NanoVDB,通过线性化树结构消除了指针依赖,大幅提升了GPU访问性能,成为实时渲染场景的理想选择。然而,NanoVDB官方主要提供CUDA接口,在DirectX 12和Vulkan等通用GPU API上的支持相对薄弱。2.2 DirectX 12与光线追踪技术DirectX 12是微软推出的新一代图形API,相比前代DirectX 11,它提供了更底层的GPU控制能力,允许开发者直接管理GPU资源分配和命令调度,从而最大化利用现代显卡的计算潜力。DirectX 12 Ultimate进一步引入了DXR(DirectX Raytracing)技术,使得实时光线追踪成为可能。DXR通过硬件加速的加速结构(Acceleration Structure)实现了高效的空间查询,已经在游戏和渲染领域得到广泛应用。在体积渲染领域,DXR的价值主要体现在两个方面。其一是加速体积与场景几何体的交互计算,如体积阴影、遮挡剔除等传统上需要额外处理的效果可以通过光线追踪自然地实现。其二是内联光线追踪(Inline Raytracing)功能的引入,使得在Compute Shader中调用TraceRay成为可能,为混合渲染架构提供了技术基础。UE5和Unity HDRP已经展示了DXR与体积渲染结合的潜力,但相关的开源实现仍然匮乏。2.3 发展趋势展望未来,体积渲染技术的发展趋势主要指向以下几个方向。首先是混合渲染架构的成熟,即结合光栅化、计算着色器和光线追踪各自的优势,在不同渲染阶段使用最适合的技术方案。其次是神经渲染技术与传统体积渲染的融合,NVIDIA提出的神经材质概念已经被拓展到体积领域,通过神经网络近似复杂的体积光照传输过程。第三是标准化和开放化的推进,随着更多开源项目的涌现,体积渲染技术的门槛将持续降低。三、研究内容、研究方法、技术路线及可行性分析3.1 研究内容本课题的研究内容可以划分为五个主要模块。第一模块是DirectX 12基础框架的搭建,包括Win32窗口系统的实现、DirectX 12设备的初始化、命令队列和描述符堆的管理,以及基础渲染管线的建立。这一模块是整个系统的基础,需要确保GPU资源能够正确分配和调度。第二模块是NanoVDB数据管线的设计与实现。具体包括VDB文件的解析与加载、CPU到GPU的高效数据传输机制,以及在Compute Shader中访问NanoVDB数据的采样器实现。由于NanoVDB的数据结构较为复杂,需要深入理解其内存布局才能实现高效的GPU访问。第三模块是体积渲染核心算法的实现。核心是以体积渲染方程为背景,基于Compute Shader的Ray Marching算法,包括光线与体积包围盒的求交、基于NanoVDB的空域跳过优化、步进采样策略,以及物理着色模型的实现。物理着色模型需要正确处理吸收、散射和自发光三种光学现象,其中散射部分还要考虑相位函数的影响。第四模块是DXR光线追踪技术的集成。这一模块作为可选扩展,主要实现体积阴影的计算和场景遮挡查询。通过构建加速结构,可以利用硬件加速的光线追踪来计算体积中的光照衰减,使渲染效果更加真实。第五模块是交互系统的设计与实现,包括自由漫游相机的控制(支持WASD移动和鼠标视角调节)、动态光源的管理(支持位置、颜色、强度调节),以及基本的画面参数调整功能。这一模块决定了用户能否直观地体验渲染效果,是系统实用性的重要保障。3.2 研究方法本课题采用的研究方法主要包括文献研究法、实验对比法和迭代开发法三种。文献研究法贯穿整个研究过程,需要系统性地研读NanoVDB官方文档、DirectX 12编程指南、DXR技术规范,以及计算机图形学领域的经典论文,特别是体积渲染和光线追踪相关的资料。通过文献研究,可以充分了解现有技术的优缺点,为系统设计提供理论支撑。实验对比法主要用于评估不同实现方案的性能和画质差异。例如,在Ray Marching中,步长的大小直接影响渲染质量和运行速度,需要通过实验找到合理的平衡点。又如,空域跳过策略的设计也需要通过对照实验来验证其有效性。实验对比的方法可以避免主观臆断,使设计决策更加科学。迭代开发法是本课题的主要开发模式。由于渲染引擎涉及多个相互依赖的模块,不可能一次性完成所有设计,因此采用快速原型、迭代完善的方式进行开发。首先实现一个最小可用的版本,验证核心技术路线可行后再逐步添加新功能。这种开发方式可以及早发现问题并调整方向,降低开发风险。3.3 技术路线整个课题的技术路线可以分为六个阶段推进。第一阶段是准备阶段,时间安排在第一周到第二周,主要完成文献调研、需求分析和系统架构设计,输出物是一份详细的设计文档,明确各模块的接口和数据流。第二阶段是基础框架开发,时间安排在第三周到第四周。这一阶段的目标是搭建起DirectX 12的运行环境和最基本的渲染管线。具体的交付物是一个可以正常显示窗口并完成清屏渲染的最小系统。这一阶段的难点在于理解DirectX 12的资源模型和命令提交机制。第三阶段是数据管线开发,时间安排在第五周到第六周。这一阶段要实现VDB文件的加载器和GPU数据传输机制。由于NanoVDB的数据结构较为复杂,需要仔细研究其存储格式,设计合理的数据转换和传输流程。交付物是能够成功加载标准VDB文件并在GPU端访问的测试程序。第四阶段是渲染核心开发,时间安排在第七周到第十周。这是整个课题最核心的部分,需要实现完整的Ray Marching渲染管线。包括光线与体积的求交算法、基于NanoVDB的空域跳过优化、不同类型光源的照度计算,以及最终的体积累积逻辑。这一阶段的交付物是一个能够渲染基本体积效果的完整渲染管线。第五阶段是交互系统开发,时间安排在第十一周到第十二周。在渲染管线的基础上添加相机控制、光照调节和参数UI等交互功能。这一阶段的重点是用户体验的优化,要确保操作流畅、反馈及时。第六阶段是优化收尾,时间安排在第十三周到第十六周。主要进行性能优化、功能完善和测试验收,最后撰写毕业设计说明书。性能优化可能包括分辨率缩放、降采样、混合精度等技术手段,需要根据实际情况灵活选择。3.4 可行性分析本课题在技术上可行。从硬件条件来看,实验室配备的RTX系列显卡完全支持DirectX 12和DXR的全部功能,可以满足开发需求。从软件基础来看,NanoVDB已经开源并提供了详细的文档,DirectX 12的编程接口也有丰富的教程和参考代码可供学习。从理论基础来看,体积渲染的核心算法已经有成熟的理论支撑,Ray Marching的实现也有大量开源项目可供参考。四、项目特色与创新点4.1 跨平台技术迁移本课题的首要特色在于将NanoVDB在DirectX 12环境中实现实时渲染。NanoVDB虽然在NVIDIA的推动下逐渐成为行业标准,但其官方实现主要面向CUDA编程模型,在DirectX 12环境下的适配工作需要开发者自行完成。本课题将深入研究NanoVDB的内存布局,设计适配DirectX 12的资源管理方案,实现GPU端的高效数据访问。这一工作本身具有一定的技术创新性,可以为后续研究者提供参考。4.2 分层架构设计在系统架构层面,本课题采用分层设计思想,将整个引擎划分为应用层、引擎层、渲染层和数据层四个层次。应用层负责用户交互和业务逻辑,引擎层提供窗口管理、资源调度等通用功能,渲染层专注于图形管线的实现,数据层处理文件解析和数据传输。这种分层架构的好处是各层职责明确,便于独立开发和测试,同时也为后续的功能扩展留出了空间。渲染层还实现了后端抽象,可以支持Compute Shader和DXR两种不同的渲染方案。4.3 混合渲染思路在渲染技术上,本课题尝试结合Compute Shader和DXR的混合渲染思路。Compute Shader负责体积数据的采样和累积,这是其擅长的计算密集型任务;DXR则用于体积阴影和场景遮挡的计算,利用硬件加速提升查询效率。这种混合方案可以在保证渲染质量的同时提升整体性能,是未来渲染引擎发展的主流方向。4.4 完整的工程实现本课题的目标是一个完整可用的工程系统,而非单纯的算法验证。这意味着不仅需要关注渲染效果的优劣,还要考虑代码的组织结构、模块的接口设计、错误处理机制、参数的可配置性和用户交互体验等工程实践问题。交付的代码将遵循良好的编码规范,关键模块配有详细注释,可以作为学习渲染引擎开发的参考资料。五、进度安排第1-2周: 国内外文献调研,明确需求,完成系统架构设计,撰写开题报告。第3-4周: 搭建DirectX 12开发环境,实现Win32窗口系统和基础渲染管线。第5-6周: 研究NanoVDB数据结构,实现VDB文件加载器和GPU数据传输模块。第7-8周: 实现Compute Shader Ray Marching核心算法,完成基础体积渲染功能。第9-10周: 优化渲染管线,实现空域跳过和物理着色模型,完善渲染质量。第11-12周: 开发交互系统,实现自由相机漫游和动态光照控制功能。第13-14周: 性能调优和测试,完善功能,撰写毕业设计说明书初稿。第15-16周: 论文修改定稿,准备答辩演示,进行项目验收。六、主要参考文献[1] Museth K. NanoVDB: A GPU-Friendly and Portable VDB Data Structure for Real-Time Rendering and Simulation[J]. ACM Transactions on Graphics, 2021, 40(4): 1-16.[2] NVIDIA. Accelerating OpenVDB on GPUs with NanoVDB[EB/OL]. NVIDIA Developer Blog, 2021.[3] Microsoft. DirectX 12 Graphics Programming Guide[EB/OL]. Microsoft Docs, 2024.[4] Microsoft. DirectX Raytracing (DXR) Technical Specification[EB/OL]. Microsoft Docs, 2024.[5] Kajiya J F. The Rendering Equation[J]. Computer Graphics, 1986, 20(4): 143-150.[6] Max N. Efficient Light Propagation for Multiple Anisotropic Scattering in Semi-Transparent Media[J]. Journal of Graphics Tools, 1995, 2(3): 21-32.[7] Wihlidal C. Optimizing the Graphics Pipeline with Compute[C]//Game Developers Conference 2019, 2019.[8] Clarberg P, Hasselgren T, Toth R, et al. Real-time Neural Appearance Models[C]//SIGGRAPH 2023, 2023.Microsoft925133737111falsefalse4005WPS Office_12.1.0.25225_F1E327BC-269C-435d-A152-05C5408002CA02022-11-23T08:41:00ZJSFW001WPS_16596162452026-03-10T04:24:09Z 2eyJoZGlkIjoiYWY4ZTYzNmU3MjAxOGQ1YzRlN2QwZjgxYzg0MWIxYTYiLCJ1c2VySWQiOiIxMzk2Mjg3NjE4In0=2052-12.1.0.252257F063531399F45D6A87B820A74E5EA18_12 \ No newline at end of file diff --git a/docs/plan/旧版题目/开题报告-王子文.doc b/docs/plan/旧版题目/开题报告-王子文.doc new file mode 100644 index 0000000..4661a24 --- /dev/null +++ b/docs/plan/旧版题目/开题报告-王子文.doc @@ -0,0 +1,3 @@ + + +武汉大学本科毕业设计(论文)开题报告题 目神经着色驱动的VDB特效实时渲染学生姓名王子文学号2022302111081所在学院计算机学院专业计算机科学与技术指导教师肖春霞职称教授一、选题目的和意义1.1 选题背景3D渲染技术正经历着从传统的“基于物理的建模(Physically Based Rendering, PBR)”向“神经网络渲染(Neural Rendering)”的范式转变。神经网络渲染融合了机器学习与计算机图形学,利用深度神经网络高效拟合复杂的光线传输过程,能够在不依赖繁重物理积分的情况下逼近真实世界的视觉效果。在这一背景下,体积特效(Volumetric Effects)如烟雾、火焰、云层和爆炸等,作为构建逼真虚拟世界的关键元素,其渲染技术的革新尤为迫切。目前,工业界主要采用 OpenVDB 格式来存储和处理这些复杂的稀疏体积数据。然而,传统的高质量体积渲染严重依赖于蒙特卡洛路径追踪(Monte Carlo Path Tracing),其计算复杂度极高,往往需要数分钟甚至数小时才能渲染一帧,这限制了其在实时交互应用(如游戏、VR/AR)中的使用。1.2 核心问题随着硬件性能的提升,原本用于离线影视级渲染的 VDB 数据,正逐渐向游戏引擎等实时渲染环境迁移。然而,这一迁移过程面临巨大挑战。现有的实时体积渲染方案(如 Ray Marching)通常为了性能而牺牲画质,难以复现离线渲染中复杂的光照效果(如多次散射、各向异性散射)。同时,高精度的 VDB 数据占用的显存空间巨大,难以在消费级显卡上流畅运行。如何兼顾“电影级画质”与“实时帧率”,同时降低存储开销,是实现这一行业迁移的关键难题。1.3 解决思路与意义本课题旨在借鉴 NVIDIA “神经材质(Neural Materials)” 的核心思想,并将其创新性地应用于体积(Volume)渲染领域。通过构建一个轻量级的神经网络(神经体积着色器),将复杂的体积光传输计算(Radiative Transfer)“烘焙”到网络权重中。本选题的意义在于:突破性能瓶颈:利用神经网络(MLP)强大的拟合能力替代复杂的物理积分计算,结合 Tensor Core 硬件加速,实现体积特效的实时推理渲染。提升实时画质:使实时引擎能够呈现原本仅存于离线渲染中的复杂光照细节,推动游戏画质向电影级迈进。二、国内外研究现状和发展趋势2.1 稀疏体积数据结构(OpenVDB & NanoVDB)OpenVDB(Museth, 2013)是电影工业的标准体积格式,但在 GPU 上运行效率较低。NVIDIA 推出的 NanoVDB(Museth, 2021)通过线性化树结构优化了 GPU 访问性能,成为实时渲染的理想载体。然而,NanoVDB 仅解决了“数据存储与访问”的问题,并未解决“光照计算复杂”的问题。2.2 神经渲染与神经着色(Neural Rendering & Shading)近年来,神经辐射场(NeRF, Mildenhall et al., 2020)展示了神经网络在视图合成上的强大能力。然而,当前大多数神经渲染方法仍依赖图像输入,缺乏对原始几何和物理材质信息的显式支持,这种“黑盒”特性限制了其在标准图形管线中的集成与编辑。针对这一问题,NVIDIA 的 Neural Materials(Rainier et al., 2022; Clarberg et al., 2023)提出了一种新范式:将复杂的表面材质模型压缩为小型 MLP,在着色器中实时运行。这种方法在保留影视级材质细节的同时,实现了 10 倍以上的性能提升和纹理压缩。2.3 发展趋势目前的趋势是将“神经材质”的成功经验从“表面(Surface)”向“体积(Volume)”拓展。即利用 NanoVDB 的稀疏结构来跳过空白区域(Space Skipping),利用神经网络来近似非线性的体积属性映射(Neural Shading)。这种结合了“显式结构加速”与“隐式计算加速”的混合管线,是未来实时渲染的重要方向。三、研究内容、研究方法、技术路线及可行性分析3.1 研究内容NanoVDB 数据管线构建:研究 OpenVDB 到 NanoVDB 的转换流程,实现稀疏体积数据在 GPU 上的高效加载与采样。神经体积着色器(Neural Volume Shader)设计:设计一个轻量级的 MLP 网络,用于替代传统的体积着色方程。输入:归一化空间坐标 (x,y,z)、视线方向、光照方向 ​、以及 NanoVDB 采样的基础属性(密度、温度等)。输出:物理光学参数,包括吸收系数、散射系数、自发光辐射率和相位函数参数。混合监督训练策略:构建基于物理的损失函数,结合 L1/L2 图像损失与物理约束(如能量守恒),确保网络输出不仅视觉逼真,且符合物理规律。Unity 实时渲染集成:在 Unity 引擎中编写 Compute Shader 或利用 TensorRT,将训练好的网络集成到渲染管线中,实现实时交互。3.2 研究方法文献研究法:深入研读 NanoVDB 源码及 Neural Materials 相关论文。实验对比法:以 Houdini + Arnold 渲染结果为 Ground Truth(真值),对比本方法与传统 Ray Marching 的画质差异(PSNR/SSIM)及帧率表现。控制变量法:探究网络层数、通道数对渲染质量与推理速度的影响。3.3 技术路线数据准备:使用 Houdini 制作烟雾/火焰特效,导出 .vdb 文件;使用 Arnold 渲染多角度、多光照条件下的高质图像作为训练集。预处理:将 .vdb 转换为 .nvdb 格式,提取稀疏体素特征。模型训练 (PyTorch):构建 MLP 网络(如 4层 x 64宽)。利用 CUDA 加速的 NanoVDB 采样器进行射线步进采样。计算预测值与 GT 的损失,反向传播更新权重。引擎部署 (Unity):将训练好的权重导出为二进制或 ONNX。在 Unity Shader 中实现 MLP 推理逻辑(前向传播)。结合 NanoVDB 的光线求交(Ray Casting)进行实时渲染。3.4 可行性分析硬件支持:实验室配备 RTX 系列显卡,支持 Tensor Core 加速和 CUDA 编程。软件基础:NanoVDB 已开源且支持 C++/CUDA;PyTorch 框架成熟;Unity 支持 Compute Shader 自定义渲染。理论支撑:辐射传输方程(RTE)理论成熟,Neural Materials 已验证了 MLP 拟合着色方程的可行性。四、项目特色与创新点跨域技术迁移(创新性):将 NVIDIA Neural Materials 在“表面材质”上的成功范式,迁移创新至“体积渲染”领域,提出“神经体积着色器”概念。稀疏-神经混合架构与几何解耦:结合 NanoVDB 的“空间稀疏性”与神经网络的“计算紧凑性”,不仅实现了存储与计算的双重优化,更实现了几何结构(NanoVDB)与外观材质(Neural Shader)的解耦。这解决了传统神经渲染方法难以编辑几何形状的痛点,支持在保持几何不变的情况下调整材质,或在保持材质风格的情况下修改几何。物理可解释性:网络输出的是中间光学参数(如散射系数)而非最终像素颜色,这使得渲染结果可以与动态光照环境交互(Relighting),保留了物理着色的灵活性。五、进度安排第1-2周:查阅文献,熟悉 NanoVDB 数据结构与 PyTorch 框架,完成开题报告。第3-4周:搭建 Houdini 数据生成管线,制作数据集,完成 VDB 到 NanoVDB 的转换测试。第5-8周:设计并实现神经体积着色器网络,在 PyTorch 中完成训练与验证,优化损失函数。第9-12周:将训练好的模型集成至 Unity 引擎,编写实时渲染 Shader,进行性能调优。第13-14周:撰写毕业论文,整理实验数据与对比结果。第15-16周:论文修改定稿,准备答辩演示。六、主要参考文献Museth, K. (2021). NanoVDB: A GPU-Friendly and Portable VDB Data Structure For Real-Time Rendering And Simulation. ACM Transactions on Graphics (TOG), 40(4).Lombardi, S., et al. (2019). Neural Volumes: Learning Dynamic Renderable Volumes from Images. ACM Transactions on Graphics (TOG), 38(4).Rainier, G., et al. (2022). Neural Materials: Unified Spectral Rendering of Layered Materials. Computer Graphics Forum.Clarberg, P., et al. (2023). Real-time Neural Appearance Models. SIGGRAPH 2023.Mildenhall, B., et al. (2020). NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis. ECCV.NVIDIA. RTX Neural Shaders & Neural Materials SDK Documentation.Microsoft7251337371130falsefalse4005WPS Office_12.1.0.24034_F1E327BC-269C-435d-A152-05C5408002CA02022-11-23T08:41:00ZJSFW001WPS_16596162452025-12-31T11:48:55Z 2eyJoZGlkIjoiYWY4ZTYzNmU3MjAxOGQ1YzRlN2QwZjgxYzg0MWIxYTYiLCJ1c2VySWQiOiIxMzk2Mjg3NjE4In0=2052-12.1.0.240347F063531399F45D6A87B820A74E5EA18_12 \ No newline at end of file diff --git a/docs/plan/旧版题目/开题报告-王子文.md b/docs/plan/旧版题目/开题报告-王子文.md new file mode 100644 index 0000000..e48394a --- /dev/null +++ b/docs/plan/旧版题目/开题报告-王子文.md @@ -0,0 +1,180 @@ +\# 武汉大学本科毕业设计(论文)开题报告 + +| 项目 | 信息 | + +| ---- | ---- | + +| 题 目 | 神经着色驱动的VDB特效实时渲染 | + +| 学生姓名 | 王子文 | + +| 学号 | 2022302111081 | + +| 所在学院 | 计算机学院 | + +| 专业 | 计算机科学与技术 | + +| 指导教师 | 肖春霞 | + +| 职称 | 教授 | + + + +\## 一、选题目的和意义 + +\### 1.1 选题背景 + +3D渲染技术正经历着从传统的“基于物理的建模(Physically Based Rendering, PBR)”向“神经网络渲染(Neural Rendering)”的范式转变。神经网络渲染融合了机器学习与计算机图形学,利用深度神经网络高效拟合复杂的光线传输过程,能够在不依赖繁重物理积分的情况下逼近真实世界的视觉效果。 + + + +在这一背景下,体积特效(Volumetric Effects)如烟雾、火焰、云层和爆炸等,作为构建逼真虚拟世界的关键元素,其渲染技术的革新尤为迫切。目前,工业界主要采用 OpenVDB 格式来存储和处理这些复杂的稀疏体积数据。然而,传统的高质量体积渲染严重依赖于蒙特卡洛路径追踪(Monte Carlo Path Tracing),其计算复杂度极高,往往需要数分钟甚至数小时才能渲染一帧,这限制了其在实时交互应用(如游戏、VR/AR)中的使用。 + + + +\### 1.2 核心问题 + +随着硬件性能的提升,原本用于离线影视级渲染的 VDB 数据,正逐渐向游戏引擎等实时渲染环境迁移。然而,这一迁移过程面临巨大挑战。现有的实时体积渲染方案(如 Ray Marching)通常为了性能而牺牲画质,难以复现离线渲染中复杂的光照效果(如多次散射、各向异性散射)。同时,高精度的 VDB 数据占用的显存空间巨大,难以在消费级显卡上流畅运行。如何兼顾“电影级画质”与“实时帧率”,同时降低存储开销,是实现这一行业迁移的关键难题。 + + + +\### 1.3 解决思路与意义 + +本课题旨在借鉴 NVIDIA “神经材质(Neural Materials)” 的核心思想,并将其创新性地应用于体积(Volume)渲染领域。通过构建一个轻量级的神经网络(神经体积着色器),将复杂的体积光传输计算(Radiative Transfer)“烘焙”到网络权重中。 + + + +本选题的意义在于: + +突破性能瓶颈:利用神经网络(MLP)强大的拟合能力替代复杂的物理积分计算,结合 Tensor Core 硬件加速,实现体积特效的实时推理渲染。 + +提升实时画质:使实时引擎能够呈现原本仅存于离线渲染中的复杂光照细节,推动游戏画质向电影级迈进。 + + + +\## 二、国内外研究现状和发展趋势 + +\### 2.1 稀疏体积数据结构(OpenVDB \& NanoVDB) + +OpenVDB(Museth, 2013)是电影工业的标准体积格式,但在 GPU 上运行效率较低。NVIDIA 推出的 NanoVDB(Museth, 2021)通过线性化树结构优化了 GPU 访问性能,成为实时渲染的理想载体。然而,NanoVDB 仅解决了“数据存储与访问”的问题,并未解决“光照计算复杂”的问题。 + + + +\### 2.2 神经渲染与神经着色(Neural Rendering \& Shading) + +近年来,神经辐射场(NeRF, Mildenhall et al., 2020)展示了神经网络在视图合成上的强大能力。然而,当前大多数神经渲染方法仍依赖图像输入,缺乏对原始几何和物理材质信息的显式支持,这种“黑盒”特性限制了其在标准图形管线中的集成与编辑。 + + + +针对这一问题,NVIDIA 的 Neural Materials(Rainier et al., 2022; Clarberg et al., 2023)提出了一种新范式:将复杂的表面材质模型压缩为小型 MLP,在着色器中实时运行。这种方法在保留影视级材质细节的同时,实现了 10 倍以上的性能提升和纹理压缩。 + + + +\### 2.3 发展趋势 + +目前的趋势是将“神经材质”的成功经验从“表面(Surface)”向“体积(Volume)”拓展。即利用 NanoVDB 的稀疏结构来跳过空白区域(Space Skipping),利用神经网络来近似非线性的体积属性映射(Neural Shading)。这种结合了“显式结构加速”与“隐式计算加速”的混合管线,是未来实时渲染的重要方向。 + + + +\## 三、研究内容、研究方法、技术路线及可行性分析 + +\### 3.1 研究内容 + +NanoVDB 数据管线构建:研究 OpenVDB 到 NanoVDB 的转换流程,实现稀疏体积数据在 GPU 上的高效加载与采样。 + +神经体积着色器(Neural Volume Shader)设计:设计一个轻量级的 MLP 网络,用于替代传统的体积着色方程。 + +输入:归一化空间坐标 (x,y,z)、视线方向、光照方向 、以及 NanoVDB 采样的基础属性(密度、温度等)。 + +输出:物理光学参数,包括吸收系数、散射系数、自发光辐射率和相位函数参数。 + +混合监督训练策略:构建基于物理的损失函数,结合 L1/L2 图像损失与物理约束(如能量守恒),确保网络输出不仅视觉逼真,且符合物理规律。 + +Unity 实时渲染集成:在 Unity 引擎中编写 Compute Shader 或利用 TensorRT,将训练好的网络集成到渲染管线中,实现实时交互。 + + + +\### 3.2 研究方法 + +文献研究法:深入研读 NanoVDB 源码及 Neural Materials 相关论文。 + +实验对比法:以 Houdini + Arnold 渲染结果为 Ground Truth(真值),对比本方法与传统 Ray Marching 的画质差异(PSNR/SSIM)及帧率表现。 + +控制变量法:探究网络层数、通道数对渲染质量与推理速度的影响。 + + + +\### 3.3 技术路线 + +数据准备:使用 Houdini 制作烟雾/火焰特效,导出 .vdb 文件;使用 Arnold 渲染多角度、多光照条件下的高质图像作为训练集。 + +预处理:将 .vdb 转换为 .nvdb 格式,提取稀疏体素特征。 + +模型训练 (PyTorch): + +构建 MLP 网络(如 4层 x 64宽)。 + +利用 CUDA 加速的 NanoVDB 采样器进行射线步进采样。 + +计算预测值与 GT 的损失,反向传播更新权重。 + +引擎部署 (Unity): + +将训练好的权重导出为二进制或 ONNX。 + +在 Unity Shader 中实现 MLP 推理逻辑(前向传播)。 + +结合 NanoVDB 的光线求交(Ray Casting)进行实时渲染。 + + + +\### 3.4 可行性分析 + +硬件支持:实验室配备 RTX 系列显卡,支持 Tensor Core 加速和 CUDA 编程。 + +软件基础:NanoVDB 已开源且支持 C++/CUDA;PyTorch 框架成熟;Unity 支持 Compute Shader 自定义渲染。 + +理论支撑:辐射传输方程(RTE)理论成熟,Neural Materials 已验证了 MLP 拟合着色方程的可行性。 + + + +\## 四、项目特色与创新点 + +跨域技术迁移(创新性):将 NVIDIA Neural Materials 在“表面材质”上的成功范式,迁移创新至“体积渲染”领域,提出“神经体积着色器”概念。 + +稀疏-神经混合架构与几何解耦:结合 NanoVDB 的“空间稀疏性”与神经网络的“计算紧凑性”,不仅实现了存储与计算的双重优化,更实现了几何结构(NanoVDB)与外观材质(Neural Shader)的解耦。这解决了传统神经渲染方法难以编辑几何形状的痛点,支持在保持几何不变的情况下调整材质,或在保持材质风格的情况下修改几何。 + +物理可解释性:网络输出的是中间光学参数(如散射系数)而非最终像素颜色,这使得渲染结果可以与动态光照环境交互(Relighting),保留了物理着色的灵活性。 + + + +\## 五、进度安排 + +第1-2周:查阅文献,熟悉 NanoVDB 数据结构与 PyTorch 框架,完成开题报告。 + +第3-4周:搭建 Houdini 数据生成管线,制作数据集,完成 VDB 到 NanoVDB 的转换测试。 + +第5-8周:设计并实现神经体积着色器网络,在 PyTorch 中完成训练与验证,优化损失函数。 + +第9-12周:将训练好的模型集成至 Unity 引擎,编写实时渲染 Shader,进行性能调优。 + +第13-14周:撰写毕业论文,整理实验数据与对比结果。 + +第15-16周:论文修改定稿,准备答辩演示。 + + + +\## 六、主要参考文献 + +1\. Museth, K. (2021). NanoVDB: A GPU-Friendly and Portable VDB Data Structure For Real-Time Rendering And Simulation. ACM Transactions on Graphics (TOG), 40(4). + +2\. Lombardi, S., et al. (2019). Neural Volumes: Learning Dynamic Renderable Volumes from Images. ACM Transactions on Graphics (TOG), 38(4). + +3\. Rainier, G., et al. (2022). Neural Materials: Unified Spectral Rendering of Layered Materials. Computer Graphics Forum. + +4\. Clarberg, P., et al. (2023). Real-time Neural Appearance Models. SIGGRAPH 2023. + +5\. Mildenhall, B., et al. (2020). NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis. ECCV. + +6\. NVIDIA. RTX Neural Shaders \& Neural Materials SDK Documentation. + diff --git a/docs/plan/深入方向规划.md b/docs/plan/深入方向规划.md new file mode 100644 index 0000000..f3a55b6 --- /dev/null +++ b/docs/plan/深入方向规划.md @@ -0,0 +1,1309 @@ +# XCVolumeRenderer 深入方向规划 + +本文档详细列出本科毕业设计可深入的所有方向,供选择和规划。 + +--- + +## 一、渲染效果提升 + +### 1.1 多散射 (Multiple Scattering) + +#### 背景 +当前实现的是单散射(Single Scattering),光线只从光源到体素再到相机弹射一次。真实云层中,光线会在体积内多次弹射,产生柔和的边缘和通透的内部效果。 + +#### 当前问题 +- 云内部过暗,缺乏体积感 +- 边缘过于锐利,不自然 +- 逆光效果不明显 + +#### 解决方案 + +**方法A:迭代多散射** +``` +for (散射次数) { + for (每个采样点) { + 计算该点的入射光(来自光源 + 其他体素的散射光) + 累积散射光 + } +} +``` +- 优点:物理正确 +- 缺点:性能开销大,O(n²) 或更高 + +**方法B:近似多散射** +``` +// 使用扩散近似(Diffusion Approximation) +// 参考: Jensen et al. "A Practical Model for Subsurface Light Transport" +float multiScatter = exp(-sigmaT * d) * diffusionTerm; +``` +- 优点:性能好 +- 缺点:近似,不够精确 + +**方法C:预计算多散射** +``` +// 离线预计算散射LUT +// 运行时查表 +Texture3D scatteringLUT; +float multiScatter = scatteringLUT.Sample(sampler, uvw); +``` +- 优点:运行时快 +- 缺点:需要额外存储 + +#### 实现步骤 +1. 实现简单的双散射(Double Scattering) +2. 观察效果变化 +3. 优化性能(重要性采样) +4. 扩展到多阶散射 + +#### 参考资料 +- Jensen, H. W., et al. "A Practical Model for Subsurface Light Transport" (SIGGRAPH 2001) +- Hachisuka, T., et al. "Progressive Photon Mapping" (SIGGRAPH 2008) +- Kutz, P., et al. "Spectral and Decomposition Tracking for Rendering Heterogeneous Volumes" (SIGGRAPH 2017) + +#### 工作量估计 +- 双散射基础实现:1周 +- 完整多散射:2-3周 +- 性能优化:1周 + +--- + +### 1.2 相函数 (Phase Function) + +#### 背景 +相函数描述光线在介质中散射的方向分布。当前使用的是均匀相函数 `return 1.0`,即各向同性散射。真实云层的相函数是各向异性的,具有强烈的前向散射特性。 + +#### 当前问题 +- 光照效果过于均匀 +- 缺乏真实云层的光晕效果 +- 逆光时的"银边"效果不明显 + +#### 相函数类型 + +**1. Henyey-Greenstein (HG) 相函数** +```hlsl +float hg_phase(float cosTheta, float g) { + float g2 = g * g; + return (1 - g2) / pow(1 + g2 - 2 * g * cosTheta, 1.5) / (4 * PI); +} +``` +- `g = 0`: 各向同性 +- `g > 0`: 前向散射(云层特性) +- `g < 0`: 后向散射 +- 参数 `g` 范围:(-1, 1) + +**2. 双 Henyey-Greenstein 相函数** +```hlsl +float double_hg_phase(float cosTheta, float g1, float g2, float w) { + return w * hg_phase(cosTheta, g1) + (1 - w) * hg_phase(cosTheta, g2); +} +``` +- 结合两个HG相函数 +- 更好地模拟真实云层 +- `g1 ≈ 0.8`(强前向),`g2 ≈ -0.2`(弱后向) + +**3. Mie 相函数** +```hlsl +// 查表实现,更精确但复杂 +// 通常用HG近似 +``` +- 物理最正确 +- 计算复杂 +- 通常用双HG近似 + +**4. Rayleigh 相函数** +```hlsl +float rayleigh_phase(float cosTheta) { + return (3 / (16 * PI)) * (1 + cosTheta * cosTheta); +} +``` +- 适用于大气散射 +- 小粒子(空气分子) + +#### 实现步骤 +1. 实现 HG 相函数 +2. 添加参数 UI 控制 `g` 值 +3. 观察不同 `g` 值的效果 +4. 实现双 HG 相函数 +5. 对比效果 + +#### 参数建议 +| 场景 | g 值 | 说明 | +|------|------|------| +| 云层 | 0.7 ~ 0.9 | 强前向散射 | +| 雾 | 0.1 ~ 0.3 | 弱前向散射 | +| 烟雾 | -0.2 ~ 0.2 | 接近各向同性 | + +#### 参考资料 +- Henyey, L. G., & Greenstein, J. L. "Diffuse radiation in the galaxy" (1941) +- Nishita, T., et al. "Display of clouds taking into account multiple anisotropic scattering and sky light" (SIGGRAPH 1996) + +#### 工作量估计 +- HG相函数实现:1-2天 +- 双HG相函数:2-3天 +- 参数UI:1天 + +--- + +### 1.3 体积自发光 (Volumetric Emission) + +#### 背景 +火焰、熔岩、霓虹气体等发光体积。除了散射外部光源,自身也发出光。 + +#### 实现方法 +```hlsl +// 在着色器中添加自发光项 +float3 emission = emissionColor * emissionIntensity * emissionMask; +float3 S = sigmaS * phase_function() * shadow * float3(1, 1, 1) + emission; +``` + +#### 扩展 +- 温度场驱动发光颜色(黑体辐射) +- 发光影响周围体积(需多散射支持) + +#### 工作量估计 +- 基础实现:1-2天 +- 温度场驱动:3-4天 + +--- + +## 二、性能优化 + +### 2.1 Temporal Reprojection + +#### 背景 +当前渲染存在噪点,尤其是阴影采样。Temporal Reprojection 利用历史帧信息进行降噪。 + +#### 原理 +``` +当前帧颜色 = α * 当前帧渲染 + (1-α) * 历史帧重投影颜色 +``` + +#### 核心步骤 + +**1. 速度缓冲 (Motion Vector)** +```hlsl +// 计算当前像素在上一帧的位置 +float2 motionVector = currentPos - previousPos; +float2 prevUV = currentUV - motionVector; +``` + +**2. 历史帧采样** +```hlsl +float3 historyColor = historyTexture.Sample(sampler, prevUV); +``` + +**3. 颜色约束 (Clamping)** +```hlsl +// 防止鬼影 +float3 minColor = min(neighbors); +float3 maxColor = max(neighbors); +historyColor = clamp(historyColor, minColor, maxColor); +``` + +**4. 混合** +```hlsl +float3 finalColor = lerp(currentColor, historyColor, 0.9); +``` + +#### 需要的资源 +- 历史帧颜色缓冲 +- 深度缓冲(当前帧 + 历史帧) +- Motion Vector 缓冲 + +#### 实现步骤 +1. 创建历史帧缓冲 +2. 实现 Motion Vector 计算 +3. 实现重投影逻辑 +4. 实现颜色约束 +5. 调试和参数调优 + +#### 注意事项 +- 相机快速移动时会产生鬼影 +- 需要处理物体移动(动态场景) +- 需要处理体积自身的旋转/移动 + +#### 参考资料 +- Karis, B. "High Quality Temporal Supersampling" (SIGGRAPH 2014) +- Schied, C., et al. "Temporal Sample Anti-Aliasing" (EGSR 2020) + +#### 工作量估计 +- 基础实现:1周 +- 调优和调试:1周 + +--- + +### 2.2 Compute Shader 重构 + +#### 背景 +当前使用 Pixel Shader 进行 Ray Marching,每个像素独立计算。Compute Shader 可以更灵活地控制线程,实现更好的优化。 + +#### 优势 + +**1. 线程组共享内存** +```hlsl +groupshared float sharedDensity[8][8]; +// 相邻像素可共享中间计算结果 +``` + +**2. 自适应工作分配** +```hlsl +// 可以跳过空像素,让活跃线程处理更多 +``` + +**3. 更好的缓存利用** +```hlsl +// 可以手动控制数据加载,优化缓存 +``` + +#### 实现架构 +``` +Compute Shader Dispatch (32x32 线程组) + ↓ +每个线程处理一个像素 + ↓ +Ray Marching + ↓ +输出到 UAV 纹理 +``` + +#### 代码示例 +```hlsl +[numthreads(8, 8, 1)] +void MainCS(uint3 DTid : SV_DispatchThreadID) +{ + float2 uv = (float2(DTid.xy) + 0.5) / Resolution; + float3 color = RayMarch(uv); + OutputTexture[DTid.xy] = float4(color, 1); +} +``` + +#### 可实现的高级优化 +- 波前追踪 (Wavefront Tracing) +- 空间跳跃优化 +- 自适应采样 + +#### 工作量估计 +- 基础重构:1-2周 +- 高级优化:2-3周 + +--- + +### 2.3 自适应步长 + +#### 背景 +当前使用固定步长,但在低密度区域可以加大步长,高密度区域减小步长。 + +#### 实现方法 + +**方法A:基于密度** +```hlsl +float density = SampleDensity(pos); +float stepSize = baseStep * (1 + (1 - density) * maxScale); +``` + +**方法B:基于梯度** +```hlsl +float gradient = length(SampleGradient(pos)); +float stepSize = baseStep / (1 + gradient * gradientScale); +``` + +**方法C:预计算重要性场** +```hlsl +// 离线预计算每个区域的重要性 +// 运行时根据重要性调整步长 +``` + +#### 注意事项 +- 步长变化过大可能导致伪影 +- 需要注意光线一致性 + +#### 工作量估计 +- 基础实现:2-3天 +- 调优:1周 + +--- + +## 三、功能扩展 + +### 3.1 多光源支持 + +#### 背景 +当前只支持单一方向光。真实场景可能有多个光源(太阳 + 天光 + 点光源)。 + +#### 实现内容 + +**1. 多方向光** +```hlsl +struct DirectionalLight { + float3 direction; + float3 color; + float intensity; +}; + +#define MAX_DIR_LIGHTS 4 +DirectionalLight dirLights[MAX_DIR_LIGHTS]; +``` + +**2. 点光源** +```hlsl +struct PointLight { + float3 position; + float3 color; + float intensity; + float radius; +}; + +float3 SamplePointLight(PointLight light, float3 pos) { + float3 dir = light.position - pos; + float dist = length(dir); + dir /= dist; + + // 衰减 + float attenuation = 1.0 / (1.0 + dist * dist); + + // 阴影采样 + float shadow = VolumetricShadow(pos, dir, dist); + + return light.color * light.intensity * attenuation * shadow; +} +``` + +**3. 聚光灯** +```hlsl +struct SpotLight { + float3 position; + float3 direction; + float3 color; + float intensity; + float innerAngle; + float outerAngle; + float range; +}; +``` + +#### 实现步骤 +1. 设计光源数据结构 +2. 实现多方向光循环 +3. 实现点光源阴影采样 +4. 实现聚光灯锥形衰减 +5. 添加参数 UI + +#### 性能考虑 +- 每个光源都需要额外的阴影采样 +- 限制光源数量或使用延迟渲染思路 + +#### 工作量估计 +- 多方向光:2-3天 +- 点光源:3-4天 +- 聚光灯:2-3天 +- UI和参数:1-2天 + +--- + +### 3.2 大气散射 + +#### 背景 +将体积渲染与天空大气结合,实现更真实的室外场景。 + +#### 核心算法 + +**1. Rayleigh 散射** +```hlsl +// 空气分子散射,产生蓝天 +float3 RayleighScattering(float cosTheta, float height) { + float3 betaR = float3(5.8e-6, 13.5e-6, 33.1e-6); // Rayleigh系数 + float density = exp(-height / 8500); // 大气密度衰减 + return betaR * density * (3 / (16 * PI)) * (1 + cosTheta * cosTheta); +} +``` + +**2. Mie 散射** +```hlsl +// 气溶胶散射,产生雾和光晕 +float3 MieScattering(float cosTheta, float g) { + float3 betaM = float3(21e-6, 21e-6, 21e-6); // Mie系数 + return betaM * HGPhase(cosTheta, g); +} +``` + +**3. 单次散射积分** +```hlsl +float3 IntegrateAtmosphere(float3 rayOrigin, float3 rayDir, float3 sunDir) { + float3 color = 0; + float transmittance = 1; + + for (int i = 0; i < steps; i++) { + float3 pos = rayOrigin + rayDir * t; + float height = length(pos) - earthRadius; + + // Rayleigh + float densityR = exp(-height / 8500); + float3 scatterR = RayleighScattering(dot(rayDir, sunDir), height); + + // Mie + float densityM = exp(-height / 1200); + float3 scatterM = MieScattering(dot(rayDir, sunDir), 0.76); + + // 光学深度 + float3 opticalDepth = (scatterR + scatterM) * stepSize; + transmittance *= exp(-opticalDepth); + color += transmittance * (scatterR + scatterM) * stepSize; + + t += stepSize; + } + + return color; +} +``` + +#### 效果 +- 蓝天 +- 日落/日出 +- 远山大气透视 +- 太阳光晕 + +#### 参考资料 +- Nishita, T., et al. "Display of The Earth Taking into Account Atmospheric Scattering" (SIGGRAPH 1993) +- Bruneton, E., & Neyret, F. "Precomputed Atmospheric Scattering" (EGSR 2008) +- Hillaire, S. "A Scalable and Production Ready Sky and Atmosphere Rendering Technique" (SIGGRAPH 2020) + +#### 工作量估计 +- 基础实现:1周 +- 优化和调参:1周 + +--- + +### 3.3 体积雾 + +#### 背景 +将体积渲染作为后处理效果,与场景几何体融合。 + +#### 实现方法 + +**1. 深度重建世界坐标** +```hlsl +float depth = depthTexture.Sample(sampler, uv); +float4 worldPos = mul(invViewProj, float4(ndc, depth, 1)); +worldPos /= worldPos.w; +``` + +**2. 沿视线积分** +```hlsl +float3 cameraPos = ...; +float3 rayDir = normalize(worldPos - cameraPos); +float dist = length(worldPos - cameraPos); + +float3 color = IntegrateVolume(cameraPos, rayDir, dist); +``` + +**3. 与场景混合** +```hlsl +float3 sceneColor = sceneTexture.Sample(sampler, uv); +float3 finalColor = lerp(sceneColor, volumeColor, volumeAlpha); +``` + +#### 工作量估计 +- 基础实现:3-4天 + +--- + +## 四、交互与控制 + +### 4.1 相机交互 + +#### 功能需求 +- 鼠标左键拖动:旋转视角 +- 鼠标右键拖动:平移 +- 鼠标滚轮:缩放 +- WASD:自由移动 + +#### 实现方法 + +**1. 弧球相机 (Arcball Camera)** +```cpp +// 围绕目标点旋转 +XMVECTOR target = XMVectorSet(0, 0, 0, 1); +float distance = 500.0f; +float yaw = 0, pitch = 0; + +void UpdateCamera() { + XMVECTOR eye = XMVectorSet( + sin(yaw) * cos(pitch) * distance, + sin(pitch) * distance, + cos(yaw) * cos(pitch) * distance, + 1.0f + ); + viewMatrix = XMMatrixLookAtLH(eye, target, XMVectorSet(0, 1, 0, 0)); +} +``` + +**2. 自由相机 (Free Camera)** +```cpp +XMVECTOR position; +float yaw = 0, pitch = 0; + +void Move(float dx, float dy, float dz) { + XMVECTOR forward = XMVectorSet(sin(yaw), 0, cos(yaw), 0); + XMVECTOR right = XMVectorSet(cos(yaw), 0, -sin(yaw), 0); + XMVECTOR up = XMVectorSet(0, 1, 0, 0); + + position += forward * dz + right * dx + up * dy; +} + +void Rotate(float dYaw, float dPitch) { + yaw += dYaw; + pitch += dPitch; + pitch = clamp(pitch, -PI/2 + 0.01f, PI/2 - 0.01f); +} +``` + +#### 输入处理 +```cpp +// Windows 消息处理 +case WM_LBUTTONDOWN: + isDragging = true; + lastMousePos = GET_MOUSE_POS(lParam); + break; + +case WM_MOUSEMOVE: + if (isDragging) { + POINT currentPos = GET_MOUSE_POS(lParam); + float dx = (currentPos.x - lastMousePos.x) * sensitivity; + float dy = (currentPos.y - lastMousePos.y) * sensitivity; + camera.Rotate(dx, dy); + lastMousePos = currentPos; + } + break; +``` + +#### 工作量估计 +- 弧球相机:2-3天 +- 自由相机:2-3天 +- 输入处理:1-2天 + +--- + +### 4.2 实时参数 UI + +#### 功能需求 +- 密度缩放 (Density Scale) +- 步长 (Step Size) +- 最大步数 (Max Steps) +- 光照方向 (Light Direction) +- 光照强度 (Light Intensity) +- 相函数参数 (Phase Function G) +- 阴影采样数 (Shadow Samples) + +#### UI 库选择 + +**选项A:Dear ImGui (推荐)** +```cpp +#include "imgui.h" + +void RenderUI() { + ImGui::Begin("Volume Parameters"); + + ImGui::SliderFloat("Density Scale", &densityScale, 0.0f, 1.0f); + ImGui::SliderFloat("Step Size", &stepSize, 0.1f, 5.0f); + ImGui::SliderInt("Max Steps", &maxSteps, 100, 5000); + ImGui::SliderFloat3("Light Dir", lightDir, -1.0f, 1.0f); + ImGui::SliderFloat("Phase G", &phaseG, -0.99f, 0.99f); + + ImGui::End(); +} +``` + +**选项B:Win32 原生控件** +- 不需要额外库 +- 实现复杂 +- 样式受限 + +#### 集成步骤 +1. 添加 ImGui 到项目 +2. 实现 D3D12 后端 +3. 创建参数面板 +4. 绑定参数到常量缓冲区 + +#### 工作量估计 +- ImGui 集成:2-3天 +- 参数面板:1-2天 + +--- + +### 4.3 体积数据编辑 + +#### 功能需求 +- 实时修改体积密度 +- 添加/删除体素 +- 画笔工具 + +#### 实现思路 + +**1. CPU 端编辑** +```cpp +// 读取当前体积数据 +std::vector volumeData = ReadVolumeData(); + +// 修改 +int x = floor(pos.x / voxelSize); +int y = floor(pos.y / voxelSize); +int z = floor(pos.z / voxelSize); +volumeData[index(x,y,z)] += strength; + +// 重新上传 GPU +UpdateGPUBuffer(volumeData); +``` + +**2. 画笔工具** +```cpp +void PaintVolume(float3 center, float radius, float strength) { + for each voxel in range: + float dist = length(voxelPos - center); + if (dist < radius) { + float falloff = 1 - dist / radius; + voxel.density += strength * falloff; + } +} +``` + +#### 挑战 +- NanoVDB 是只读结构,需要重建 +- 或改用 3D Texture + +#### 工作量估计 +- 基础编辑:1周 +- 画笔工具:3-4天 + +--- + +## 五、数据生成 + +### 5.1 程序化云生成 + +#### 背景 +使用 Noise 函数程序化生成云层,无需外部数据文件。 + +#### 核心算法 + +**1. Perlin Noise** +```hlsl +float perlinNoise(float3 p) { + // 梯度噪声实现 + float3 i = floor(p); + float3 f = frac(p); + float3 u = f * f * (3 - 2 * f); // smoothstep + + return lerp( + lerp(lerp(hash(i + float3(0,0,0)), hash(i + float3(1,0,0)), u.x), + lerp(hash(i + float3(0,1,0)), hash(i + float3(1,1,0)), u.x), u.y), + lerp(lerp(hash(i + float3(0,0,1)), hash(i + float3(1,0,1)), u.x), + lerp(hash(i + float3(0,1,1)), hash(i + float3(1,1,1)), u.x), u.y), + u.z + ); +} +``` + +**2. Fractal Brownian Motion (FBM)** +```hlsl +float fbm(float3 p, int octaves) { + float value = 0; + float amplitude = 0.5; + float frequency = 1; + + for (int i = 0; i < octaves; i++) { + value += amplitude * perlinNoise(p * frequency); + amplitude *= 0.5; + frequency *= 2; + } + + return value; +} +``` + +**3. 云密度函数** +```hlsl +float cloudDensity(float3 pos) { + // 基础形状(球体或盒子) + float shape = sphere(pos, center, radius); + + // 噪声扰动 + float noise = fbm(pos * scale, 5); + + // 密度 + float density = shape * noise; + + // 阈值和锐化 + density = smoothstep(threshold, threshold + edgeSoftness, density); + + return density; +} +``` + +**4. Worley Noise (细胞噪声)** +```hlsl +// 用于云的细节和孔洞 +float worleyNoise(float3 p) { + float minDist = 1e10; + int3 cell = floor(p); + + for (int x = -1; x <= 1; x++) + for (int y = -1; y <= 1; y++) + for (int z = -1; z <= 1; z++) { + int3 neighbor = cell + int3(x, y, z); + float3 point = neighbor + hash3(neighbor); + float dist = distance(p, point); + minDist = min(minDist, dist); + } + + return minDist; +} +``` + +#### 云层模型 + +**Cumulus (积云)** +- 底部平坦,顶部蓬松 +- 使用多个 FBM 叠加 +- 高度衰减 + +**Stratus (层云)** +- 薄层状 +- 低频噪声 +- 均匀分布 + +**Cirrus (卷云)** +- 高空,纤维状 +- 高频噪声 +- 方向性 + +#### 动态演化 +```hlsl +// 随时间演化 +float density = cloudDensity(pos + wind * time); + +// 形态变化 +float growth = sin(time * growthSpeed); +density *= 1 + growth * 0.2; +``` + +#### 参考资料 +- Ebert, D. S., et al. "Texturing & Modeling: A Procedural Approach" +- Gili, A. "The Real-Time Volumetric Cloudscapes of Horizon Zero Dawn" (SIGGRAPH 2015) +- Hillaire, S. "Physically Based Sky, Atmosphere and Cloud Rendering in Frostbite" (SIGGRAPH 2016) + +#### 工作量估计 +- Perlin/FBM 实现:2-3天 +- Worley Noise:2天 +- 云密度函数:3-4天 +- 参数调优:1周 + +--- + +### 5.2 离线流体模拟器 + +#### 背景 +实现 CPU 端流体模拟,导出 OpenVDB/NanoVDB 格式。 + +#### 核心算法:Navier-Stokes 方程 + +``` +∂u/∂t = -(u·∇)u - ∇p/ρ + ν∇²u + f +∇·u = 0 +``` + +其中: +- u:速度场 +- p:压力场 +- ρ:密度 +- ν:粘度 +- f:外力 + +#### 求解步骤 + +**1. 对流 (Advection)** +```cpp +void advect(VelocityField& u, ScalarField& q, float dt) { + for each cell (i, j, k): + // 回溯粒子位置 + Vec3 pos = Vec3(i, j, k) - u(i, j, k) * dt; + // 插值采样 + q_new(i, j, k) = interpolate(q, pos); +} +``` + +**2. 扩散 (Diffusion)** +```cpp +void diffuse(ScalarField& q, float viscosity, float dt) { + // Jacobi 迭代 + for (int iter = 0; iter < iterations; iter++) { + for each cell (i, j, k): + q_new(i, j, k) = (q(i-1,j,k) + q(i+1,j,k) + + q(i,j-1,k) + q(i,j+1,k) + + q(i,j,k-1) + q(i,j,k+1) + + q_old(i,j,k) * alpha) / (6 + alpha); + } +} +``` + +**3. 压力求解 (Pressure Solve)** +```cpp +void project(VelocityField& u) { + // 计算散度 + for each cell: + divergence(i, j, k) = -0.5 * (u(i+1,j,k).x - u(i-1,j,k).x + + u(i,j+1,k).y - u(i,j-1,k).y + + u(i,j,k+1).z - u(i,j,k-1).z); + + // Jacobi 迭代求解压力 + for (int iter = 0; iter < iterations; iter++) { + for each cell: + p_new(i, j, k) = (p(i-1,j,k) + p(i+1,j,k) + + p(i,j-1,k) + p(i,j+1,k) + + p(i,j,k-1) + p(i,j,k+1) + - divergence(i,j,k)) / 6; + } + + // 速度校正 + for each cell: + u(i, j, k).x -= 0.5 * (p(i+1,j,k) - p(i-1,j,k)); + u(i, j, k).y -= 0.5 * (p(i,j+1,k) - p(i,j-1,k)); + u(i, j, k).z -= 0.5 * (p(i,j,k+1) - p(i,j,k-1)); +} +``` + +**4. 外力 (External Forces)** +```cpp +void addForce(VelocityField& u, Vec3 forcePos, Vec3 forceDir, float strength) { + for each cell near forcePos: + u(i, j, k) += forceDir * strength * falloff(distance); +} +``` + +#### 烟雾模拟扩展 + +**密度场** +```cpp +// 对流密度 +advect(u, density, dt); + +// 添加烟雾源 +for each source cell: + density(i, j, k) = sourceStrength; + +// 衰减 +density *= (1 - decay * dt); +``` + +**温度场** +```cpp +// 浮力 +for each cell: + float buoyancy = temperature(i,j,k) * buoyancyStrength; + u(i,j,k).y += buoyancy * dt; +``` + +**涡度约束 (Vorticity Confinement)** +```cpp +// 增加细节 +Vec3 curl = computeCurl(u); +Vec3 N = normalize(curl); +Vec3 omega = curl; +u += dt * vorticityStrength * N * omega; +``` + +#### OpenVDB 集成 + +```cpp +#include +#include + +void exportToVDB(const ScalarField& density, const std::string& filename) { + openvdb::initialize(); + + // 创建网格 + openvdb::FloatGrid::Ptr grid = openvdb::FloatGrid::create(); + openvdb::FloatGrid::Accessor accessor = grid->getAccessor(); + + // 填充数据 + for each active voxel (i, j, k): + openvdb::Coord coord(i, j, k); + accessor.setValue(coord, density(i, j, k)); + + // 保存 + openvdb::io::File file(filename); + file.write({grid}); + file.close(); +} +``` + +#### NanoVDB 转换 + +```cpp +#include + +void convertToNanoVDB(const std::string& openvdbFile, const std::string& nanovdbFile) { + // 读取 OpenVDB + openvdb::io::File file(openvdbFile); + openvdb::GridBase::Ptr baseGrid = file.readGrid("density"); + + // 转换 + auto handle = nanovdb::openToNanoVDB(baseGrid); + + // 保存 + nanovdb::io::writeToFile(nanovdbFile, handle); +} +``` + +#### 工作流程 +``` +1. 初始化网格和场 +2. 循环帧: + a. 对流速度场 + b. 添加外力 + c. 扩散(粘度) + d. 压力求解 + e. 对流密度/温度 + f. 导出当前帧 +3. 批量转换为 NanoVDB +``` + +#### 参考资料 +- Bridson, R. "Fluid Simulation for Computer Graphics" (书籍) +- Stam, J. "Stable Fluids" (SIGGRAPH 1999) +- Fedkiw, R., et al. "Visual Simulation of Smoke" (SIGGRAPH 2001) + +#### 工作量估计 +- 基础流体求解器:2周 +- 烟雾扩展:1周 +- OpenVDB 集成:1周 +- NanoVDB 导出:3-4天 +- UI 和参数:1周 + +--- + +### 5.3 多格式导入 + +#### 支持格式 + +| 格式 | 描述 | 库 | +|------|------|-----| +| OpenVDB (.vdb) | 行业标准 | openvdb 库 | +| DDS 体积纹理 | DirectX 格式 | DirectX | +| Raw 体素数据 | 自定义格式 | 手动解析 | + +#### 实现思路 +```cpp +class VolumeLoader { +public: + virtual bool load(const std::string& path) = 0; + virtual float sample(int x, int y, int z) const = 0; + virtual Vec3 size() const = 0; +}; + +class OpenVDBLoader : public VolumeLoader { ... }; +class DDSLoader : public VolumeLoader { ... }; +class RawLoader : public VolumeLoader { ... }; +``` + +#### 工作量估计 +- OpenVDB 支持:3-4天 +- DDS 支持:2-3天 +- 统一接口:1-2天 + +--- + +## 六、高级算法 + +### 6.1 重要性采样 + +#### 背景 +根据体积密度分布,在重要区域增加采样密度,在空区域减少采样。 + +#### 方法 + +**1. 基于密度的重要性采样** +```hlsl +// 根据密度调整采样概率 +float pdf = density / totalDensity; +float step = baseStep / pdf; +``` + +**2. 分层采样** +```hlsl +// 将光线分成段,每段内均匀采样 +for each segment: + float randomOffset = rand(); + float samplePos = segmentStart + randomOffset * segmentLength; +``` + +**3. 多重要性采样** +```hlsl +// 结合多种采样策略 +float sampleByDensity = ...; +float sampleByLight = ...; +float weight = misWeight(densityWeight, lightWeight); +``` + +#### 工作量估计 +- 基础实现:3-4天 +- 优化:1周 + +--- + +### 6.2 屏幕空间降噪 + +#### 背景 +低采样率导致的噪点,通过屏幕空间滤波器降噪。 + +#### 算法 + +**1. 双边滤波 (Bilateral Filter)** +```hlsl +float3 bilateralFilter(float2 uv, float3 centerColor, float centerDepth) { + float3 sum = 0; + float weightSum = 0; + + for each neighbor: + float3 neighborColor = sample(neighborUV); + float neighborDepth = sampleDepth(neighborUV); + + float spatialWeight = gaussian(distance); + float rangeWeight = gaussian(length(neighborColor - centerColor)); + float depthWeight = gaussian(abs(neighborDepth - centerDepth)); + + float weight = spatialWeight * rangeWeight * depthWeight; + sum += neighborColor * weight; + weightSum += weight; + + return sum / weightSum; +} +``` + +**2. SVGF (Spatiotemporal Variance-Guided Filtering)** +- Temporal 累积 +- 空间滤波 +- 方差估计 + +**3. BMFR (Blockwise Multi-Order Feature Regression)** +- 块处理 +- 特征回归 + +#### 参考资料 +- Schied, C., et al. "Spatiotemporal Variance-Guided Filtering" (EGSR 2017) + +#### 工作量估计 +- 双边滤波:2-3天 +- SVGF:2-3周 + +--- + +## 七、场景融合 + +### 7.1 体积与场景遮挡 + +#### 问题 +当前体积渲染不考虑场景几何体的遮挡。 + +#### 解决方案 + +**1. 深度测试** +```hlsl +// 从深度缓冲重建世界坐标 +float depth = depthTexture.Sample(sampler, uv); +float3 sceneWorldPos = reconstructWorldPos(uv, depth); + +// 计算到场景的距离 +float sceneDist = length(sceneWorldPos - cameraPos); + +// Ray Marching 时限制最大距离 +float tmax = min(rayTmax, sceneDist); +``` + +**2. 阴影遮挡** +```hlsl +// 场景几何体遮挡体积 +float sceneShadow = 1.0; +if (isOccludedByScene(pos)) { + sceneShadow = 0.0; +} +``` + +#### 工作量估计 +- 深度测试:2-3天 +- 完整遮挡:1周 + +--- + +### 7.2 阴影接收 + +#### 问题 +体积应该接收场景几何体的阴影。 + +#### 解决方案 +```hlsl +float sceneShadow = SampleSceneShadowMap(pos); +float3 S = sigmaS * phase_function() * shadow * sceneShadow; +``` + +#### 工作量估计 +- 基础实现:2-3天 + +--- + +## 八、应用场景 + +### 8.1 动态天气系统 + +#### 功能 +- 云层动态演化 +- 日出日落光照变化 +- 雨雾效果 + +#### 实现 +```hlsl +// 云层演化 +float timeOfDay = sin(time * dayCycleSpeed); +float cloudDensity = baseDensity * (0.5 + 0.5 * timeOfDay); + +// 光照变化 +float3 sunColor = lerp(sunriseColor, noonColor, timeOfDay); +float3 ambientColor = lerp(nightAmbient, dayAmbient, timeOfDay); + +// 雾气 +float fogDensity = fogBase + fogVariation * sin(time); +``` + +#### 工作量估计 +- 1-2周 + +--- + +### 8.2 火焰/爆炸效果 + +#### 需求 +- 温度场驱动 +- 黑体辐射颜色 +- 自发光 + +#### 实现 +```hlsl +// 温度到颜色 (黑体辐射) +float3 temperatureToColor(float T) { + // Planck 定律近似 + float x = T / 10000.0; + float3 color; + color.r = 1.0; + color.g = clamp(1.0 - exp(-5.0 * x), 0, 1); + color.b = clamp(1.0 - exp(-10.0 * x), 0, 1); + return color; +} + +// 发光 +float3 emission = temperatureToColor(temperature) * emissionIntensity; +float3 S = sigmaS * phase_function() * shadow + emission; +``` + +#### 工作量估计 +- 1周 + +--- + +## 九、推荐方案总结 + +### 方案A:渲染深化(学术向) +``` +多散射 + 相函数 + Temporal Reprojection +``` +- 难度:⭐⭐⭐⭐ +- 工作量:4-5周 +- 论文价值:高 +- 适合:想发论文/读研 + +### 方案B:工程完整(展示向) +``` +相机交互 + 参数UI + 多光源 + 大气散射 +``` +- 难度:⭐⭐⭐ +- 工作量:3-4周 +- 展示效果:好 +- 适合:答辩演示 + +### 方案C:离线工具链(创新向) +``` +离线流体模拟器 + OpenVDB集成 + NanoVDB导出 +``` +- 难度:⭐⭐⭐⭐⭐ +- 工作量:6-8周 +- 创新性:强 +- 适合:想深入图形学 + +### 方案D:程序化生成(创意向) +``` +程序化云生成 + 参数控制 + 动态天气 +``` +- 难度:⭐⭐⭐⭐ +- 工作量:3-4周 +- 展示性:强 +- 适合:想展示效果 + +### 方案E:平衡方案(推荐) +``` +多散射 + Temporal Reprojection + 相函数 + 程序化扰动动画 +``` +- 难度:⭐⭐⭐⭐ +- 工作量:4-5周 +- 效果提升明显 +- 有技术深度 +- 工作量可控 + +--- + +## 十、时间规划建议 + +### 单方向深入(4-5周) + +| 阶段 | 内容 | 时间 | +|------|------|------| +| 第1周 | 多散射基础实现 | 7天 | +| 第2周 | 多散射优化 + 相函数 | 7天 | +| 第3周 | Temporal Reprojection | 7天 | +| 第4周 | 程序化扰动 + 效果调优 | 7天 | +| 第5周 | 文档 + 测试 | 7天 | + +### 多方向扩展(6-8周) + +| 阶段 | 内容 | 时间 | +|------|------|------| +| 第1-2周 | 渲染效果提升 | 14天 | +| 第3-4周 | 性能优化 | 14天 | +| 第5-6周 | 交互与控制 | 14天 | +| 第7周 | 效果调优 | 7天 | +| 第8周 | 文档 + 测试 | 7天 | + +--- + +## 十一、参考资料汇总 + +### 论文 +1. Jensen, H. W., et al. "A Practical Model for Subsurface Light Transport" (SIGGRAPH 2001) +2. Kutz, P., et al. "Spectral and Decomposition Tracking for Rendering Heterogeneous Volumes" (SIGGRAPH 2017) +3. Stam, J. "Stable Fluids" (SIGGRAPH 1999) +4. Fedkiw, R., et al. "Visual Simulation of Smoke" (SIGGRAPH 2001) +5. Karis, B. "High Quality Temporal Supersampling" (SIGGRAPH 2014) +6. Schied, C., et al. "Spatiotemporal Variance-Guided Filtering" (EGSR 2017) + +### 书籍 +1. Bridson, R. "Fluid Simulation for Computer Graphics" +2. Ebert, D. S., et al. "Texturing & Modeling: A Procedural Approach" +3. Pharr, M., et al. "Physically Based Rendering: From Theory to Implementation" + +### 开源项目 +1. OpenVDB: https://github.com/AcademySoftwareFoundation/openvdb +2. NanoVDB: https://github.com/AcademySoftwareFoundation/nanovdb +3. Mantaflow: https://mantaflow.uni-mainz.de/ +4. Dear ImGui: https://github.com/ocornut/imgui + +--- + +*文档版本: 1.0* +*更新日期: 2026年3月* \ No newline at end of file diff --git a/docs/plan/第一阶段计划.md b/docs/plan/第一阶段计划.md new file mode 100644 index 0000000..05bcb37 --- /dev/null +++ b/docs/plan/第一阶段计划.md @@ -0,0 +1,151 @@ +# XCEngine 游戏引擎 - 第一阶段计划 + +> **目标**: 构建核心基础层,为上层渲染系统提供底层依赖 +> **版本**: 1.0 +> **日期**: 2026-03-13 + +--- + +## 阶段目标 + +第一阶段聚焦于引擎底层基础设施的建设,确保后续渲染系统开发有稳定的基础。 + +--- + +## 模块规划 + +### 1.1 数学库 (Math Library) + +| 项目 | 内容 | +|------|------| +| **优先级** | P0 | +| **预计工作量** | 5天 | +| **包含类型** | `Vector2`, `Vector3`, `Vector4`, `Matrix3x3`, `Matrix4x4`, `Quaternion`, `Transform`, `Color`, `Rect`, `RectInt`, `Viewport`, `Ray`, `Sphere`, `Box`, `Plane`, `Frustum`, `Bounds`, `AABB`, `OBB` | +| **功能要求** | 向量运算、矩阵变换、四元数、欧拉角转换、视锥体剔除基础 | + +### 1.2 Core 基础类型 + +| 项目 | 内容 | +|------|------| +| **优先级** | P0 | +| **预计工作量** | 2天 | +| **包含类型** | 基础类型别名 (`int8`, `uint8`, `int16`, `uint16`, `int32`, `uint32`, `int64`, `uint64`, `byte`)、`RefCounted`、`Ref`、`UniqueRef`、`Event` | +| **功能要求** | 基础类型别名、引用计数、智能指针、事件系统 | +| **依赖** | 无 | + +### 1.3 线程系统 (Threading) + +| 项目 | 内容 | +|------|------| +| **优先级** | P0 | +| **预计工作量** | 4天 | +| **包含类型** | `ITask`, `LambdaTask`, `TaskGroup`, `TaskSystem`, `TaskSystemConfig`, `Mutex`, `SpinLock`, `ReadWriteLock`, `Thread` | +| **功能要求** | 任务调度、依赖管理、并行计算、同步原语 | +| **依赖** | Core基础类型 | + +### 1.4 内存管理 (Memory Management) + +| 项目 | 内容 | +|------|------| +| **优先级** | P0 | +| **预计工作量** | 3天 | +| **包含类型** | `IAllocator`, `LinearAllocator`, `PoolAllocator`, `ProxyAllocator`, `MemoryManager` | +| **功能要求** | 内存分配、追踪、泄漏检测、线性/池化分配策略 | +| **依赖** | 线程系统(ProxyAllocator需要Mutex) | + +### 1.5 容器库 (Containers) + +| 项目 | 内容 | +|------|------| +| **优先级** | P0 | +| **预计工作量** | 3天 | +| **包含类型** | `Array`, `String`, `String::npos`, `HashMap` | +| **功能要求** | 动态数组、字符串操作(含npos常量)、哈希映射 | +| **依赖** | Core基础类型, 内存管理 | + +### 1.6 日志与调试系统 + +| 项目 | 内容 | +|------|------| +| **优先级** | P1 | +| **预计工作量** | 2天 | +| **包含类型** | `Logger`, `ConsoleLogSink`, `FileLogSink`, `FileWriter`, `Profiler`, `Assert` | +| **功能要求** | 分级日志、分类输出、文件写入、性能分析、断言 | +| **依赖** | Core基础类型, 容器库(String) | + +--- + +## 时间安排 + +| 周次 | 内容 | +|------|------| +| 第1周 | 数学库 + Core基础类型 | +| 第2周 | 线程系统 + 内存管理 | +| 第3周 | 容器库 + 日志系统 | + +> 注:内存管理依赖线程系统完成(ProxyAllocator需要Mutex),因此调整顺序 + +--- + +## 测试方案 + +### 测试框架 +- **推荐**: Google Test (gtest) 或 Doctest + +### 测试用例设计 + +| 模块 | 测试类别 | 测试用例示例 | +|------|---------|-------------| +| **Math** | 向量运算 | `Vector3::Dot`, `Cross`, `Normalize`, `Lerp` 精度测试 | +| **Math** | 矩阵运算 | `Matrix4x4::TRS`, `LookAt`, `Perspective` 结果正确性 | +| **Math** | 四元数 | `FromEulerAngles`, `Slerp`, `ToMatrix4x4` 精度验证 | +| **Core** | 引用计数 | `RefCounted` 多线程安全释放 | +| **Core** | 事件系统 | 订阅/取消订阅、线程安全调用 | +| **Threading** | 任务系统 | 依赖链、优先级、并行For、TaskSystemConfig | +| **Threading** | 同步原语 | 锁竞争、死锁检测 | +| **Memory** | 分配器 | 边界检查、碎片率、线性分配器回滚测试 | +| **Memory** | 泄漏检测 | 分配/释放计数、峰值追踪 | +| **Containers** | Array | 边界访问、迭代器、内存增长策略 | +| **Containers** | String | 子串、查找、大小写转换 | +| **Containers** | HashMap | 冲突处理、负载因子重分布 | +| **Logger** | 日志级别 | 过滤、分类、格式化 | + +### 执行命令 + +```bash +# 编译并运行所有单元测试 +cmake --build build --target xcengine_tests +./build/tests/xcengine_tests.exe + +# 性能基准测试 +./build/tests/xcengine_tests.exe --benchmark +``` + +--- + +## 验收标准 + +- [ ] 数学库通过全部运算正确性测试 +- [ ] Core基础类型(引用计数、智能指针)工作正常 +- [ ] 线程系统在高并发下稳定运行 +- [ ] 内存分配器无内存泄漏 +- [ ] 容器操作边界安全 +- [ ] 日志系统输出格式正确 + +--- + +## 依赖关系 + +``` +Math Library (无依赖) + │ + ├──▶ Core 基础类型 (无依赖) + │ │ + │ ├──▶ Threading (依赖 Core) + │ │ + │ ├──▶ Memory Management (依赖 Threading) + │ │ │ + │ │ └──▶ Containers (依赖 Memory, Core) + │ │ + │ └──▶ Logging & Debug (依赖 Core, Containers) +``` diff --git a/docs/plan/第三阶段计划.md b/docs/plan/第三阶段计划.md new file mode 100644 index 0000000..0cf8cd7 --- /dev/null +++ b/docs/plan/第三阶段计划.md @@ -0,0 +1,335 @@ +# 第三阶段计划:OpenGL 后端实现 + +> **目标**:实现 OpenGL 后端,完成 RHI 跨平台图形抽象 +> **阶段**:第三阶段 +> **前置依赖**:第二阶段 RHI 抽象层与 D3D12 后端 + +--- + +## 3.1 阶段目标 + +在已有 RHI 抽象层和 D3D12 后端的基础上,实现 OpenGL 后端: +- 复用现有抽象接口 +- 对接 OpenGL (GLFW + GLAD) +- 支持最小渲染系统验证 + +--- + +## 3.2 目录结构 + +``` +engine/include/XCEngine/RHI/OpenGL/ +├── OpenGLCommon.h # OpenGL 公共定义与辅助函数 +├── OpenGLEnum.h # RHI 枚举 → OpenGL 枚举转换层 +├── OpenGLDevice.h # 设备初始化 +├── OpenGLDevice.cpp +├── OpenGLSwapChain.h # 交换链(GLFW 窗口) +├── OpenGLSwapChain.cpp +├── OpenGLCommandList.h # 命令列表封装 +├── OpenGLCommandList.cpp +├── OpenGLBuffer.h # VBO/IBO/UBO 管理 +├── OpenGLBuffer.cpp +├── OpenGLTexture.h # 纹理管理 +├── OpenGLTexture.cpp +├── OpenGLShader.h # GLSL 着色器 +├── OpenGLShader.cpp +├── OpenGLPipelineState.h # VAO + Program + State +├── OpenGLPipelineState.cpp +├── OpenGLRenderTarget.h # FBO + RTV +├── OpenGLRenderTarget.cpp +├── OpenGLDepthStencil.h # 深度模板 +├── OpenGLDepthStencil.cpp +├── OpenGLDescriptorHeap.h # Texture Unit 模拟 +├── OpenGLDescriptorHeap.cpp +├── OpenGLFence.h # 同步 +├── OpenGLFence.cpp +├── OpenGLQueryHeap.h # 查询堆 +├── OpenGLQueryHeap.cpp +├── OpenGLRootSignature.h # 简化实现 +├── OpenGLRootSignature.cpp +├── OpenGLSampler.h # 采样器 +├── OpenGLSampler.cpp +├── OpenGLResourceView.h # 视图基类 +├── OpenGLResourceView.cpp +└── OpenGLRenderTargetView.h # 渲染目标视图 + ├── OpenGLRenderTargetView.cpp + ├── OpenGLDepthStencilView.h + ├── OpenGLDepthStencilView.cpp + ├── OpenGLShaderResourceView.h + ├── OpenGLShaderResourceView.cpp + ├── OpenGLUnorderedAccessView.h + ├── OpenGLUnorderedAccessView.cpp + ├── OpenGLConstantBufferView.h + └── OpenGLConstantBufferView.cpp +``` + +--- + +## 3.3 任务拆分 + +### 3.3.1 基础准备 + +**任务 3.1:OpenGLEnum.h - 枚举转换层** + +实现 RHI 枚举到 OpenGL 枚举的转换: +- `Format` → `GLenum` +- `PrimitiveTopology` → `GLenum` +- `BlendOp` / `BlendFactor` → `GLenum` +- `ComparisonFunc` → `GLenum` +- `ResourceStates` → `GLenum` (简化) +- `ShaderType` → `GLenum` + +**任务 3.2:OpenGLCommon.h - 公共定义** + +- OpenGL 初始化辅助函数 +- 格式支持检测 +- 错误检查宏 +- GLAD 加载器封装 + +--- + +### 3.3.2 核心组件实现 + +**任务 3.3:OpenGLDevice - 设备实现** + +实现 `OpenGLDevice` 类: +- GLFW 窗口创建 +- GLAD 初始化 +- OpenGL 上下文配置 +- 设备信息查询 + +```cpp +class OpenGLDevice : public IRHIDevice { +public: + bool Initialize(void* windowHandle, bool enableDebug = false); + GLFWwindow* GetWindow() const { return m_window; } + + // IRHIDevice 实现... + +private: + GLFWwindow* m_window; + HGLRC m_glContext; +}; +``` + +**任务 3.4:OpenGLSwapChain - 交换链实现** + +实现 `OpenGLSwapChain` 类: +- GLFW 窗口管理 +- 双缓冲切换 +- 帧缓冲 resize 处理 + +**任务 3.5:OpenGLShader - 着色器实现** + +实现 `OpenGLShader` 类: +- GLSL 源码加载 +- `glShaderSource` + `glCompileShader` +- 编译错误获取 +- 反射数据提取(可选) + +**任务 3.6:OpenGLBuffer - 缓冲区实现** + +实现 `OpenGLBuffer` 类: +- VBO 创建与管理 +- IBO 索引缓冲 +- UBO uniform 缓冲 +- Buffer mapping + +**任务 3.7:OpenGLTexture - 纹理实现** + +实现 `OpenGLTexture` 类: +- 2D 纹理创建 +- 纹理参数设置 +- Mipmap 生成 +- 纹理绑定 + +**任务 3.8:OpenGLPipelineState - 管线状态实现** + +实现 `OpenGLPipelineState` 类: +- VAO 管理 +- Shader Program 链接 +- 状态缓存(blend, depth, rasterizer) +- 输入布局映射 + +**任务 3.9:OpenGLCommandList - 命令列表实现** + +实现 `OpenGLCommandList` 类: +- 状态缓存与批量提交 +- `glDrawArrays` / `glDrawElements` 封装 +- 视口裁剪设置 +- 渲染目标绑定 + +**任务 3.10:OpenGLFence - 同步实现** + +实现 `OpenGLFence` 类: +- `glFenceSync` 封装 +- CPU 等待实现 + +**任务 3.11:OpenGLDescriptorHeap - 描述符堆实现** + +实现 `OpenGLDescriptorHeap` 类: +- Texture Unit 数组管理 +- 简化版描述符绑定 + +--- + +### 3.3.3 视图实现 + +**任务 3.12:OpenGLRenderTargetView - 渲染目标视图** + +- Framebuffer 对象管理 +- 颜色附件绑定 + +**任务 3.13:OpenGLDepthStencilView - 深度模板视图** + +- Depth/stencil buffer 管理 +- FBO 深度附件 + +**任务 3.14:OpenGLShaderResourceView - 着色器资源视图** + +- 纹理视图绑定到 Texture Unit + +**任务 3.15:OpenGLUnorderedAccessView - 无序访问视图** + +- SSBO 管理 + +**任务 3.16:OpenGLConstantBufferView - 常量缓冲区视图** + +- UBO 绑定 + +--- + +## 3.4 D3D12 与 OpenGL 关键差异 + +| D3D12 组件 | OpenGL 对应 | 差异说明 | +|------------|-------------|----------| +| `ID3D12Device` | `OpenGLDevice` | GLFW + GLAD 初始化 | +| `ID3D12CommandQueue` | 简化 | OpenGL 无需显式命令队列 | +| `ID3D12CommandList` | `OpenGLCommandList` | 封装立即模式渲染 | +| `ID3D12DescriptorHeap` | `OpenGLDescriptorHeap` | 使用 Texture Unit 模拟 | +| `ID3D12PipelineState` | `OpenGLPipelineState` | VAO + Program + State | +| `ID3D12RootSignature` | 简化 | 使用 uniform binding | +| `ID3D12Fence` | `OpenGLFence` | glFenceSync | +| `ID3D12SwapChain` | `OpenGLSwapChain` | GLFW 窗口管理 | +| `ID3D12Buffer` | `OpenGLBuffer` | VBO/IBO/UBO | +| `ID3D12Texture` | `OpenGLTexture` | GL 纹理对象 | +| `ID3D12Shader` | `OpenGLShader` | GLSL 编译 | +| `ID3D12QueryHeap` | `OpenGLQueryHeap` | GL 查询对象 | + +--- + +## 3.5 实现顺序 + +``` +阶段 3.1: 基础准备 (1天) + ├── 3.1.1 OpenGLEnum.h (枚举转换) + └── 3.1.2 OpenGLCommon.h (公共定义) + +阶段 3.2: 核心组件 (4天) + ├── 3.2.1 OpenGLDevice + ├── 3.2.2 OpenGLSwapChain + ├── 3.2.3 OpenGLShader + ├── 3.2.4 OpenGLBuffer + ├── 3.2.5 OpenGLTexture + ├── 3.2.6 OpenGLPipelineState + └── 3.2.7 OpenGLCommandList + +阶段 3.3: 辅助组件 (2天) + ├── 3.3.1 OpenGLFence + ├── 3.3.2 OpenGLDescriptorHeap + ├── 3.3.3 OpenGLQueryHeap + ├── 3.3.4 OpenGLSampler + └── 3.3.5 OpenGLRootSignature + +阶段 3.4: 视图实现 (1天) + ├── 3.4.1 OpenGLRenderTargetView + ├── 3.4.2 OpenGLDepthStencilView + ├── 3.4.3 OpenGLShaderResourceView + ├── 3.4.4 OpenGLUnorderedAccessView + └── 3.4.5 OpenGLConstantBufferView + +阶段 3.5: 集成测试 (1天) + ├── 窗口创建与渲染循环 + ├── 简单模型渲染测试 + └── 与 mvs/OpenGL 功能对比验证 +``` + +--- + +## 3.6 关键技术点 + +### 3.6.1 状态管理 + +OpenGL 是状态机模式: +- 在 `OpenGLCommandList` 中缓存当前状态 +- 绘制前检查状态变化,仅调用变化的 GL 函数 +- 避免冗余状态设置 + +### 3.6.2 资源绑定 + +D3D12: Descriptor Heap + Root Signature +OpenGL: Texture Unit + Uniform Location + +```cpp +// OpenGL 方式 +glActiveTexture(GL_TEXTURE0 + slot); +glBindTexture(GL_TEXTURE_2D, textureID); +glUniform1i(location, slot); +``` + +### 3.6.3 着色器编译 + +```cpp +// GLSL 编译 +GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); +glShaderSource(vertexShader, 1, &vertexSource, nullptr); +glCompileShader(vertexShader); + +GLuint program = glCreateProgram(); +glAttachShader(program, vertexShader); +glAttachShader(program, fragmentShader); +glLinkProgram(program); +``` + +### 3.6.4 VAO 管理 + +```cpp +// Vertex Array Object +GLuint vao; +glGenVertexArrays(1, &vao); +glBindVertexArray(vao); +glEnableVertexAttribArray(0); +glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); +``` + +### 3.6.5 帧缓冲 + +```cpp +// Framebuffer Object +GLuint fbo; +glGenFramebuffers(1, &fbo); +glBindFramebuffer(GL_FRAMEBUFFER, fbo); +glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0); +glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthID, 0); +``` + +--- + +## 3.7 验收标准 + +1. **编译通过**:所有头文件和实现文件能够无错误编译 +2. **接口完整**:所有 RHI 抽象接口都有 OpenGL 实现 +3. **功能验证**: + - 能够创建 GLFW 窗口并初始化 OpenGL 上下文 + - 能够渲染简单的几何体 + - 能够加载和显示纹理 + - 能够呈现到屏幕 +4. **功能对比**:与现有 mvs/OpenGL 功能一致 + +--- + +## 3.8 后续阶段依赖 + +- 第四阶段:渲染管线(RenderPipeline)需要 RHI 多后端支持 +- 材质系统需要统一的 Shader 接口 +- 跨平台渲染验证需要 OpenGL 后端 diff --git a/docs/plan/第二阶段计划.md b/docs/plan/第二阶段计划.md new file mode 100644 index 0000000..5ccb290 --- /dev/null +++ b/docs/plan/第二阶段计划.md @@ -0,0 +1,829 @@ +# 第二阶段计划:RHI 渲染硬件抽象层 + +> **目标**:构建跨平台的渲染硬件抽象层,支持多后端(D3D12、Vulkan等) +> **阶段**:第二阶段 +> **前置依赖**:第一阶段核心基础层(数学库、内存管理、线程系统) + +--- + +## 2.1 阶段目标 + +实现完整的RHI抽象层,提供: +- 统一的图形API抽象接口 +- D3D12后端完整实现 +- 资源管理(纹理、缓冲区) +- 命令流提交机制 +- 同步与同步原语 + +--- + +## 2.2 目录结构 + +``` +engine/include/XCEngine/RHI/ # 渲染硬件抽象层(公开API) +├── Enums.h # 枚举定义(独立编号,跨平台) +├── Types.h # 通用类型定义 +├── RHISystem.h # RHI 系统入口 +├── RHIDevice.h # 抽象设备接口 +├── Resource.h # 资源基类接口 +├── ResourceView.h # 资源视图基类接口 +├── RenderTargetView.h # 渲染目标视图接口 +├── DepthStencilView.h # 深度模板视图接口 +├── ShaderResourceView.h # 着色器资源视图接口 +├── UnorderedAccessView.h # 无序访问视图接口 +├── ConstantBufferView.h # 常量缓冲区视图接口 +├── CommandQueue.h # 命令队列 +├── CommandList.h # 命令列表 +├── CommandAllocator.h # 命令分配器 +├── Fence.h # 同步围栏 +├── DescriptorHeap.h # 描述符堆 +├── QueryHeap.h # 查询堆 +├── RootSignature.h # 根签名 +├── PipelineState.h # 管线状态 +├── Sampler.h # 采样器 +├── SwapChain.h # 交换链 +├── Texture.h # 纹理资源 +├── Buffer.h # 缓冲区资源 +├── Shader.h # 着色器 +└── D3D12/ # D3D12 后端实现 + ├── D3D12Enum.h # 枚举转换层(RHI→D3D12) + ├── D3D12Device.h + ├── D3D12Device.cpp + ├── D3D12CommandList.h + ├── D3D12CommandList.cpp + ├── D3D12CommandQueue.h + ├── D3D12CommandQueue.cpp + ├── D3D12CommandAllocator.h + ├── D3D12CommandAllocator.cpp + ├── D3D12Fence.h + ├── D3D12Fence.cpp + ├── D3D12DescriptorHeap.h + ├── D3D12DescriptorHeap.cpp + ├── D3D12QueryHeap.h + ├── D3D12QueryHeap.cpp + ├── D3D12RootSignature.h + ├── D3D12RootSignature.cpp + ├── D3D12PipelineState.h + ├── D3D12PipelineState.cpp + ├── D3D12Sampler.h + ├── D3D12Sampler.cpp + ├── D3D12SwapChain.h + ├── D3D12SwapChain.cpp + ├── D3D12Texture.h + ├── D3D12Texture.cpp + ├── D3D12Buffer.h + ├── D3D12Buffer.cpp + ├── D3D12Shader.h + ├── D3D12Shader.cpp + ├── D3D12RenderTargetView.h + ├── D3D12RenderTargetView.cpp + ├── D3D12DepthStencilView.h + ├── D3D12DepthStencilView.cpp + ├── D3D12ShaderResourceView.h + ├── D3D12ShaderResourceView.cpp + ├── D3D12UnorderedAccessView.h + ├── D3D12UnorderedAccessView.cpp + ├── D3D12ConstantBufferView.h + ├── D3D12ConstantBufferView.cpp + └── D3D12Common.h # 公共定义 +``` + +--- + +## 2.3 任务拆分 + +### 2.3.1 基础枚举与类型定义 + +**任务 2.1:Enums.h - 枚举定义** + +定义所有渲染相关的枚举类型: +- `Format` - 像素格式 +- `ResourceStates` - 资源状态 +- `ShaderType` - 着色器类型 +- `PrimitiveTopology` - 图元拓扑 +- `CullMode` / `FillMode` - 剔除/填充模式 +- `BlendOp` / `BlendFactor` - 混合操作/因子 +- `ComparisonFunc` - 比较函数 +- `StencilOp` - 模板操作 +- `TextureType` - 纹理类型 +- `BufferType` - 缓冲区类型 +- `QueryType` - 查询类型 +- `DescriptorType` - 描述符类型 +- `PipelineType` - 管线类型 +- `CommandQueueType` - 命令队列类型 +- `LoadAction` / `StoreAction` - 渲染目标加载/存储操作 +- `PresentFlags` - 呈现标志 +- `IndirectDrawArguments` - 间接绘制参数 +- `IndirectDispatchArguments` - 间接调度参数 + +**任务 2.1.2:类型定义 - Types.h** + +定义通用结构体(不依赖特定图形API): +- `Viewport` - 视口 +- `Rect` - 矩形区域 +- `Color` - 颜色 +- `ClearValue` - 清空值 +- `ShaderCompileDesc` - 着色器编译描述 +- `ShaderCompileResult` - 着色器编译结果 +- `ShaderCompileMacro` - 着色器宏定义 +- `InputElementDesc` - 输入元素描述 +- `InputLayoutDesc` - 输入布局描述 +- `VertexBufferBinding` - 顶点缓冲区绑定 +- `TextureCopyLocation` - 纹理复制位置 +- `DescriptorHandle` - 描述符句柄(通用类型) +- `GPUDescriptorHandle` - GPU描述符句柄 +- `CPUDescriptorHandle` - CPU描述符句柄 +- `ResourceBarrierDesc` - 资源屏障描述 +- `SubresourceRange` - 子资源范围 +- `TextureDesc` - 纹理描述 +- `BufferDesc` - 缓冲区描述 +- `RenderTargetDesc` - 渲染目标描述 +- `DepthStencilDesc` - 深度模板描述 +- `DescriptorHeapDesc` - 描述符堆描述 +- `CommandQueueDesc` - 命令队列描述 +- `CommandListDesc` - 命令列表描述 +- `CommandAllocatorDesc` - 命令分配器描述 +- `FenceDesc` - 围栏描述 +- `QueryHeapDesc` - 查询堆描述 +- `RootSignatureDesc` - 根签名描述 +- `SamplerDesc` - 采样器描述 +- `PipelineStateDesc` - 管线状态描述 +- `SwapChainDesc` - 交换链描述 +- `BlendStateDesc` - 混合状态描述 +- `DepthStencilStateDesc` - 深度模板状态描述 +- `RasterizerStateDesc` - 光栅化状态描述 +- `ShaderBytecode` - 着色器字节码 +- `ShaderBindingInfo` - 着色器绑定信息 +- `RenderTargetViewDesc` - 渲染目标视图描述 +- `DepthStencilViewDesc` - 深度模板视图描述 +- `ShaderResourceViewDesc` - 着色器资源视图描述 +- `UnorderedAccessViewDesc` - 无序访问视图描述 +- `ConstantBufferViewDesc` - 常量缓冲区视图描述 +- `FormatSupport` - 格式支持信息 + +### 2.3.2 核心接口定义 + +**任务 2.2:RHISystem.h - RHI系统入口** + +```cpp +struct RHISystemConfig { + void* nativeWindowHandle = nullptr; // HWND on Windows + uint32_t width = 1280; + uint32_t height = 720; + bool fullscreen = false; + uint32_t backBufferCount = 2; + bool enableDebugLayer = false; + bool enableGBV = false; +}; + +class RHISystem { +public: + static RHISystem& Get(); + + bool Initialize(const RHISystemConfig& config); + void Shutdown(); + + IRHIDevice* GetDevice(); + ISwapChain* GetSwapChain(); + + void BeginFrame(); + void EndFrame(); + + // 窗口管理 + void Resize(uint32_t width, uint32_t height); + void SetFullscreen(bool fullscreen); + bool IsFullscreen() const; + +private: + std::unique_ptr m_device; + std::unique_ptr m_swapChain; +}; +``` + +**任务 2.3:RHIDevice.h - 抽象设备接口** + +```cpp +struct DeviceInfo { + String deviceName; + String driverVersion; + uint64_t dedicatedVideoMemory; + uint64_t dedicatedSystemMemory; + uint64_t sharedSystemMemory; + uint32_t vendorId; + uint32_t deviceId; + bool supportsRaytracing; + bool supportsMeshShaders; + bool supportsSamplerFeedback; +}; + +class IRHIDevice { +public: + virtual ~IRHIDevice() = default; + + // 资源创建 + virtual ICommandQueue* CreateCommandQueue(const CommandQueueDesc& desc) = 0; + virtual ICommandList* CreateCommandList(const CommandListDesc& desc) = 0; + virtual ICommandAllocator* CreateCommandAllocator(const CommandAllocatorDesc& desc) = 0; + virtual IFence* CreateFence(const FenceDesc& desc) = 0; + virtual IDescriptorHeap* CreateDescriptorHeap(const DescriptorHeapDesc& desc) = 0; + virtual IQueryHeap* CreateQueryHeap(const QueryHeapDesc& desc) = 0; + virtual IRootSignature* CreateRootSignature(const RootSignatureDesc& desc) = 0; + virtual IPipelineState* CreatePipelineState(const PipelineStateDesc& desc) = 0; + virtual ISampler* CreateSampler(const SamplerDesc& desc) = 0; + virtual ITexture* CreateTexture(const TextureDesc& desc) = 0; + virtual IBuffer* CreateBuffer(const BufferDesc& desc) = 0; + virtual ISwapChain* CreateSwapChain(const SwapChainDesc& desc) = 0; + + // 视图创建 + virtual IRenderTargetView* CreateRenderTargetView(IResource* resource, const RenderTargetViewDesc& desc) = 0; + virtual IDepthStencilView* CreateDepthStencilView(IResource* resource, const DepthStencilViewDesc& desc) = 0; + virtual IShaderResourceView* CreateShaderResourceView(IResource* resource, const ShaderResourceViewDesc& desc) = 0; + virtual IUnorderedAccessView* CreateUnorderedAccessView(IResource* resource, const UnorderedAccessViewDesc& desc) = 0; + virtual IConstantBufferView* CreateConstantBufferView(IResource* resource, const ConstantBufferViewDesc& desc) = 0; + + // 着色器编译 + virtual IShader* CompileShader(const ShaderCompileDesc& desc) = 0; + + // 查询 + virtual void GetDeviceInfo(DeviceInfo& info) const = 0; + virtual FormatSupport GetFormatSupport(Format format) const = 0; +}; +``` + +**任务 2.4:CommandQueue.h - 命令队列接口** + +```cpp +class ICommandQueue { +public: + virtual ~ICommandQueue() = default; + + virtual void ExecuteCommandLists(uint32_t count, ICommandList** lists) = 0; + virtual void Signal(IFence* fence, uint64_t value) = 0; + virtual void Wait(IFence* fence, uint64_t value) = 0; + virtual uint64_t GetCompletedValue() = 0; + virtual void WaitForIdle() = 0; + + virtual CommandQueueType GetType() const = 0; + virtual uint64_t GetTimestampFrequency() const = 0; +}; +``` + +**任务 2.5:CommandList.h - 命令列表接口** + +```cpp +class ICommandList { +public: + virtual ~ICommandList() = default; + + // 状态转换 + virtual void TransitionBarrier(uint32_t count, const ResourceBarrierDesc* barriers) = 0; + virtual void UAVBarrier(IResource* resource = nullptr) = 0; + virtual void AliasBarrier(IResource* before, IResource* after) = 0; + + // 渲染状态 + virtual void SetPipelineState(IPipelineState* pso) = 0; + virtual void SetRootSignature(IRootSignature* signature) = 0; + virtual void SetViewport(const Viewport& viewport) = 0; + virtual void SetViewports(uint32_t count, const Viewport* viewports) = 0; + virtual void SetScissorRect(const Rect& rect) = 0; + virtual void SetScissorRects(uint32_t count, const Rect* rects) = 0; + virtual void SetPrimitiveTopology(PrimitiveTopology topology) = 0; + virtual void SetRenderTargets(uint32_t count, IResource** renderTargets, IResource* depthStencil) = 0; + + // 绑定 + virtual void SetVertexBuffer(uint32_t slot, IBuffer* buffer, uint32_t offset, uint32_t stride) = 0; + virtual void SetVertexBuffers(uint32_t startSlot, uint32_t count, const VertexBufferBinding* bindings) = 0; + virtual void SetIndexBuffer(IBuffer* buffer, uint32_t offset, Format indexFormat) = 0; + virtual void SetConstantBuffer(uint32_t rootParameterIndex, IBuffer* buffer, uint32_t offset, uint32_t size) = 0; + virtual void SetShaderResource(uint32_t rootParameterIndex, IResource* resource) = 0; + virtual void SetUnorderedAccess(uint32_t rootParameterIndex, IResource* resource) = 0; + virtual void SetDescriptorHeap(IDescriptorHeap* heap) = 0; + virtual void SetGraphicsDescriptorTable(uint32_t rootParameterIndex, GPUDescriptorHandle baseHandle) = 0; + virtual void SetComputeDescriptorTable(uint32_t rootParameterIndex, GPUDescriptorHandle baseHandle) = 0; + + // 渲染状态设置 + virtual void SetStencilRef(uint8_t stencilRef) = 0; + virtual void SetBlendFactor(const float blendFactor[4]) = 0; + virtual void SetDepthBias(float depthBias, float slopeScaledDepthBias, float depthBiasClamp) = 0; + + // 绘制 + virtual void Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertex, uint32_t startInstance) = 0; + virtual void DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndex, int32_t baseVertex, uint32_t startInstance) = 0; + virtual void DrawInstancedIndirect(IBuffer* argBuffer, uint32_t alignedByteOffset) = 0; + virtual void DrawIndexedInstancedIndirect(IBuffer* argBuffer, uint32_t alignedByteOffset) = 0; + + // 清空 + virtual void ClearRenderTargetView(IResource* renderTarget, const float color[4]) = 0; + virtual void ClearDepthStencilView(IResource* depthStencil, uint32_t clearFlags, float depth, uint8_t stencil) = 0; + virtual void ClearUnorderedAccessView(IResource* unorderedAccess, const float values[4]) = 0; + + // 复制 + virtual void CopyResource(IResource* dst, IResource* src) = 0; + virtual void CopyBuffer(IBuffer* dst, uint64_t dstOffset, IBuffer* src, uint64_t srcOffset, uint64_t size) = 0; + virtual void CopyTexture(ITexture* dst, const TextureCopyLocation& dstLocation, ITexture* src, const TextureCopyLocation& srcLocation) = 0; + + // 查询 + virtual void BeginQuery(IQueryHeap* queryHeap, QueryType type, uint32_t index) = 0; + virtual void EndQuery(IQueryHeap* queryHeap, QueryType type, uint32_t index) = 0; + virtual void ResolveQuery(IQueryHeap* queryHeap, QueryType type, uint32_t startIndex, uint32_t count, IBuffer* resultBuffer, uint64_t resultOffset) = 0; + + // 提交 + virtual void Close() = 0; + virtual void Reset(ICommandAllocator* allocator) = 0; + + // 计算着色器 + virtual void Dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ) = 0; + virtual void DispatchIndirect(IBuffer* argBuffer, uint32_t alignedByteOffset) = 0; + + // Bundle (用于命令复用) + virtual void ExecuteBundle(ICommandList* bundle) = 0; +}; +``` + +**任务 2.6:其他核心接口** + +- `Resource.h` - 资源基类接口(所有资源的共同基类) +- `ResourceView.h` - 资源视图基类接口 +- `RenderTargetView.h` - 渲染目标视图接口 +- `DepthStencilView.h` - 深度模板视图接口 +- `ShaderResourceView.h` - 着色器资源视图接口 +- `UnorderedAccessView.h` - 无序访问视图接口 +- `ConstantBufferView.h` - 常量缓冲区视图接口 +- `CommandAllocator.h` - 命令分配器接口 +```cpp +class ICommandAllocator { +public: + virtual ~ICommandAllocator() = default; + virtual void Reset() = 0; + virtual bool IsReady() const = 0; +}; +``` +- `Fence.h` - 同步围栏接口 +```cpp +class IFence { +public: + virtual ~IFence() = default; + virtual void Signal(uint64_t value) = 0; + virtual void Wait(uint64_t value) = 0; + virtual uint64_t GetCompletedValue() = 0; + virtual void* GetEventHandle() = 0; +}; +``` +- `DescriptorHeap.h` - 描述符堆接口 +```cpp +class IDescriptorHeap { +public: + virtual ~IDescriptorHeap() = default; + virtual CPUDescriptorHandle GetCPUDescriptorHandle(uint32_t index) = 0; + virtual GPUDescriptorHandle GetGPUDescriptorHandle(uint32_t index) = 0; + virtual uint32_t GetDescriptorCount() const = 0; + virtual DescriptorType GetType() const = 0; +}; +``` +- `QueryHeap.h` - 查询堆接口 +```cpp +class IQueryHeap { +public: + virtual ~IQueryHeap() = default; + virtual void* GetNativeHandle() const = 0; + virtual QueryType GetType() const = 0; + virtual uint32_t GetCount() const = 0; +}; +``` +- `RootSignature.h` - 根签名接口 +```cpp +class IRootSignature { +public: + virtual ~IRootSignature() = default; + virtual void* GetNativeHandle() const = 0; + virtual uint32_t GetParameterCount() const = 0; +}; +``` +- `PipelineState.h` - 管线状态接口 +```cpp +class IPipelineState { +public: + virtual ~IPipelineState() = default; + virtual void* GetNativeHandle() const = 0; + virtual PipelineType GetType() const = 0; +}; +``` +- `Sampler.h` - 采样器接口 +```cpp +class ISampler { +public: + virtual ~ISampler() = default; + virtual void* GetNativeHandle() const = 0; +}; +``` +- `SwapChain.h` - 交换链接口 +```cpp +class ISwapChain { +public: + virtual ~ISwapChain() = default; + + virtual uint32_t GetCurrentBackBufferIndex() = 0; + virtual IResource* GetBackBuffer(uint32_t index) = 0; + virtual void Present(uint32_t syncInterval, PresentFlags flags) = 0; + virtual void Resize(uint32_t width, uint32_t height) = 0; + virtual void SetFullscreen(bool fullscreen) = 0; + virtual bool IsFullscreen() const = 0; + + virtual void* GetNativeHandle() const = 0; +}; +``` +- `Texture.h` - 纹理资源接口 +```cpp +class ITexture : public IResource { +public: + virtual uint32_t GetWidth() const = 0; + virtual uint32_t GetHeight() const = 0; + virtual uint32_t GetDepth() const = 0; + virtual uint32_t GetMipLevels() const = 0; + virtual uint32_t GetArraySize() const = 0; + virtual Format GetFormat() const = 0; + virtual TextureType GetTextureType() const = 0; + + virtual IShaderResourceView* GetOrCreateSRV() = 0; + virtual IRenderTargetView* GetOrCreateRTV(uint32_t mipSlice = 0, uint32_t arraySlice = 0) = 0; + virtual IDepthStencilView* GetOrCreateDSV(uint32_t mipSlice = 0, uint32_t arraySlice = 0) = 0; + virtual IUnorderedAccessView* GetOrCreateUAV(uint32_t mipSlice = 0, uint32_t arraySlice = 0) = 0; +}; +``` +- `Buffer.h` - 缓冲区资源接口 +```cpp +class IBuffer : public IResource { +public: + virtual uint64_t GetSize() const = 0; + virtual uint32_t GetStride() const = 0; + virtual BufferType GetBufferType() const = 0; + + virtual IConstantBufferView* GetOrCreateCBV() = 0; + virtual IShaderResourceView* GetOrCreateSRV() = 0; + virtual IUnorderedAccessView* GetOrCreateUAV() = 0; +}; +``` +- `Shader.h` - 着色器接口 +```cpp +class IShader { +public: + virtual ~IShader() = default; + + virtual const void* GetBytecode() const = 0; + virtual size_t GetBytecodeSize() const = 0; + virtual ShaderType GetType() const = 0; + + virtual const InputLayoutDesc& GetInputLayout() const = 0; + virtual const ShaderBindingInfo& GetBindingInfo() const = 0; +}; +``` +- `RenderTarget.h` - 渲染目标接口 +```cpp +class IRenderTarget { +public: + virtual ~IRenderTarget() = default; + + virtual ITexture* GetTexture() = 0; + virtual IRenderTargetView* GetRTV() = 0; + virtual uint32_t GetWidth() const = 0; + virtual uint32_t GetHeight() const = 0; + virtual Format GetFormat() const = 0; +}; +``` +- `DepthStencil.h` - 深度模板接口 +```cpp +class IDepthStencil { +public: + virtual ~IDepthStencil() = default; + + virtual ITexture* GetTexture() = 0; + virtual IDepthStencilView* GetDSV() = 0; + virtual IShaderResourceView* GetSRV() = 0; + virtual uint32_t GetWidth() const = 0; + virtual uint32_t GetHeight() const = 0; + virtual Format GetFormat() const = 0; +}; +``` + +**任务 2.7:Resource.h - 资源基类接口** + +```cpp +class IResource { +public: + virtual ~IResource() = default; + + virtual void* GetNativeHandle() const = 0; + virtual ResourceStates GetState() const = 0; + virtual void SetState(ResourceStates state) = 0; + + virtual uint64_t GetGPUAddress() const = 0; + virtual size_t GetSize() const = 0; + + virtual const String& GetName() const = 0; + virtual void SetName(const String& name) = 0; +}; +``` + +**任务 2.8:ResourceView.h - 资源视图基类接口** + +```cpp +class IResourceView { +public: + virtual ~IResourceView() = default; + virtual void* GetNativeHandle() const = 0; + virtual IResource* GetResource() const = 0; +}; +``` + +--- + +### 2.3.3 D3D12 后端实现 + +**任务 2.9:D3D12Common.h - 公共定义** + +D3D12相关的公共定义和辅助函数: +- 格式转换映射 +- 描述符大小计算 +- 资源状态转换 +- 辅助工具函数 + +**任务 2.10:D3D12Device - 设备实现** + +实现 `D3D12Device` 类: +- ID3D12Device 封装 +- IDXGIFactory 创建与管理 +- 所有资源创建接口实现 +- 适配器信息查询 +- 功能级别支持检测 +- 内存信息查询 +- 设备移除与恢复处理 + +**任务 2.11:D3D12CommandQueue - 命令队列实现** + +实现 `D3D12CommandQueue` 类: +- ID3D12CommandQueue 封装 +- 命令列表执行 +- 围栏同步 +- 时间戳频率查询 + +**任务 2.12:D3D12CommandList - 命令列表实现** + +实现 `D3D12CommandList` 类: +- ID3D12GraphicsCommandList 封装 +- 所有渲染命令实现 +- 状态追踪与验证 +- 资源追踪 + +**任务 2.13:D3D12CommandAllocator - 命令分配器实现** + +实现 `D3D12CommandAllocator` 类: +- ID3D12CommandAllocator 封装 +- 重置管理 + +**任务 2.14:D3D12Fence - 围栏实现** + +实现 `D3D12Fence` 类: +- ID3D12Fence 封装 +- CPU/GPU同步 +- 事件句柄管理 + +**任务 2.15:D3D12DescriptorHeap - 描述符堆实现** + +实现 `D3D12DescriptorHeap` 类: +- ID3D12DescriptorHeap 封装 +- CPU/GPU描述符句柄管理 +- 描述符分配/释放 +- 堆增量大小计算 + +**任务 2.16:D3D12RootSignature - 根签名实现** + +实现 `D3D12RootSignature` 类: +- ID3D12RootSignature 封装 +- 根参数配置 +- 描述符表布局 +- 静态采样器 + +**任务 2.17:D3D12PipelineState - 管线状态实现** + +实现 `D3D12PipelineState` 类: +- ID3D12PipelineState 封装 +- 图形管线描述构建 +- 计算管线描述构建 +- 混合状态 +- 深度模板状态 +- 输入布局 +- 顶点/像素着色器绑定 + +**任务 2.18:D3D12Sampler - 采样器实现** + +实现 `D3D12Sampler` 类: +- D3D12_SAMPLER_DESC 封装 +- 静态采样器支持 + +**任务 2.19:D3D12QueryHeap - 查询堆实现** + +实现 `D3D12QueryHeap` 类: +- ID3D12QueryHeap 封装 +- 时间戳查询 +- 遮挡查询 +- 流水线统计 + +**任务 2.20:D3D12SwapChain - 交换链实现** + +实现 `D3D12SwapChain` 类: +- IDXGISwapChain3 封装 +- 帧缓冲管理 +- 呈现模式配置 +- 完整屏幕支持 + +**任务 2.21:D3D12Texture - 纹理实现** + +实现 `D3D12Texture` 类: +- ID3D12Resource 封装 +- 纹理描述 +- 子资源管理 +- 视图创建(SRV, RTV, DSV, UAV) +- 状态管理 + +**任务 2.22:D3D12Buffer - 缓冲区实现** + +实现 `D3D12Buffer` 类: +- ID3D12Resource 封装 +- 缓冲区描述 +- 视图创建(SRV, CBV, UAV) +- 上传堆管理 +- 默认堆管理 + +**任务 2.23:D3D12Shader - 着色器实现** + +实现 `D3D12Shader` 类: +- 着色器字节码管理 +- 反射数据提取 +- 输入布局构建 + +**任务 2.24:D3D12RenderTargetView - 渲染目标视图实现** + +实现 `D3D12RenderTargetView` 类: +- ID3D12RenderTargetView 封装 +- 描述符创建与管理 + +**任务 2.25:D3D12DepthStencilView - 深度模板视图实现** + +实现 `D3D12DepthStencilView` 类: +- ID3D12DepthStencilView 封装 +- 描述符创建与管理 + +**任务 2.26:D3D12ShaderResourceView - 着色器资源视图实现** + +实现 `D3D12ShaderResourceView` 类: +- ID3D12ShaderResourceView 封装 +- 描述符创建与管理 + +**任务 2.27:D3D12UnorderedAccessView - 无序访问视图实现** + +实现 `D3D12UnorderedAccessView` 类: +- ID3D12UnorderedAccessView 封装 +- 描述符创建与管理 + +**任务 2.28:D3D12ConstantBufferView - 常量缓冲区视图实现** + +实现 `D3D12ConstantBufferView` 类: +- ID3D12ConstantBufferView 封装 +- 描述符创建与管理 + +--- + +## 2.4 实现顺序 + +``` +阶段 2.1: 基础枚举与类型 (1天) + ├── 2.1.1 Enums.h [已完成] + │ └── RHI枚举定义(独立编号) + ├── 2.1.2 Types.h (通用类型定义) + └── 2.1.3 D3D12Enum.h [已完成] + └── 枚举转换层(RHI→D3D12) + +阶段 2.2: 核心接口定义 (3天) + ├── 2.2.1 RHISystem.h + ├── 2.2.2 RHIDevice.h + ├── 2.2.3 Resource.h (资源基类) + ├── 2.2.4 ResourceView.h (视图基类) + ├── 2.2.5 CommandQueue.h + ├── 2.2.6 CommandList.h + └── 2.2.7 其他接口文件 + +阶段 2.3: D3D12 后端实现 (7天) + ├── 2.3.1 D3D12Common.h + ├── 2.3.2 D3D12Device + ├── 2.3.3 D3D12Resource / D3D12Texture / D3D12Buffer + ├── 2.3.4 D3D12CommandQueue + ├── 2.3.5 D3D12CommandList + ├── 2.3.6 D3D12CommandAllocator + ├── 2.3.7 D3D12Fence + ├── 2.3.8 D3D12DescriptorHeap + ├── 2.3.9 D3D12RootSignature + ├── 2.3.10 D3D12PipelineState + ├── 2.3.11 D3D12Sampler + ├── 2.3.12 D3D12QueryHeap + ├── 2.3.13 D3D12SwapChain + ├── 2.3.14 D3D12Shader + ├── 2.3.15 D3D12RenderTargetView + ├── 2.3.16 D3D12DepthStencilView + ├── 2.3.17 D3D12ShaderResourceView + ├── 2.3.18 D3D12UnorderedAccessView + └── 2.3.19 D3D12ConstantBufferView + +阶段 2.4: 集成测试 (1天) + ├── 窗口创建与交换链关联 + ├── 渲染循环基本框架 + └── 简单的清屏测试 +``` + +--- + +## 2.5 验收标准 + +1. **编译通过**:所有头文件和实现文件能够无错误编译 +2. **接口完整**:所有定义的接口都有D3D12实现 +3. **功能验证**: + - 能够创建窗口并初始化D3D12设备 + - 能够创建命令队列和命令列表 + - 能够执行基本的渲染命令(清屏) + - 能够处理窗口消息和呈现 +4. **代码质量**: + - 遵循编码规范 + - 必要的注释和文档 + - 错误处理完善 + +--- + +## 2.6 关键技术点 + +### 2.6.1 资源状态管理 + +D3D12要求严格的状态管理: +- 资源必须处于正确的状态才能使用 +- 状态转换通过 `TransitionBarrier` +- 常用状态:`D3D12_RESOURCE_STATE_GENERIC_READ`, `D3D12_RESOURCE_STATE_RENDER_TARGET`, `D3D12_RESOURCE_STATE_DEPTH_WRITE` 等 + +### 2.6.2 描述符管理 + +- 描述符堆类型:CBV/SRV/UAV, Sampler, RTV, DSV +- GPU可见描述符堆用于渲染 +- CPU可见描述符堆用于描述符拷贝 +- 描述符递增大小计算 + +### 2.6.3 根签名设计 + +- 根参数类型:根常量、根描述符、根描述符表 +- 描述符表:描述符数组 +- 静态采样器:不可变的采样器配置 + +### 2.6.4 管线状态对象 + +- 图形管线:混合、深度、模板、光栅化、输入布局、顶点/像素/几何/ Hull/Domain着色器 +- 计算管线:根签名、CS着色器 + +### 2.6.5 视图接口设计 + +- 每种视图类型(RTV/DSV/SRV/UAV/CBV)都有独立接口 +- 视图持有对底层资源的引用 +- 视图描述符确定资源的解释方式 + +### 2.6.6 着色器编译 + +- 使用D3DCompiler API或dxc编译HLSL +- 支持着色器反射获取输入布局和资源绑定信息 +- 支持着色器宏定义和include处理 + +### 2.6.7 跨平台抽象设计原则 + +- 所有接口使用抽象类型,不暴露D3D12特定类型 +- GPUDescriptorHandle/CPUDescriptorHandle 作为通用句柄类型 +- 资源状态使用统一的ResourceStates枚举 +- 创建描述符结构体独立于特定API +- RHI枚举使用独立编号,通过转换层转换为特定API枚举 + +### 2.6.8 枚举转换层 + +RHI枚举使用独立编号(与任何图形API无关),通过转换层转换为特定API: +```cpp +// RHI枚举(独立编号) +enum class FillMode { Wireframe, Solid }; + +// D3D12转换层 +inline D3D12_FILL_MODE ToD3D12(FillMode mode) { + switch (mode) { + case FillMode::Wireframe: return D3D12_FILL_MODE_WIREFRAME; + case FillMode::Solid: return D3D12_FILL_MODE_SOLID; + } +} +``` + +--- + +## 2.7 后续阶段依赖 + +- 第三阶段:渲染管线(RenderPipeline)需要RHI作为基础 +- 材质系统需要RHI的Shader和PipelineState +- 场景渲染需要CommandList提交绘制命令 diff --git a/docs/plan/第四阶段计划_资源系统.md b/docs/plan/第四阶段计划_资源系统.md new file mode 100644 index 0000000..7d68319 --- /dev/null +++ b/docs/plan/第四阶段计划_资源系统.md @@ -0,0 +1,5199 @@ +# 资源系统设计与实现 + +> **目标**:构建游戏引擎资源管理系统,支持多种资源类型的加载、缓存、异步加载 +> **阶段**:第四阶段(与RHI并行开发) +> **前置依赖**:第一阶段核心基础层(容器、内存管理、线程系统) + +--- + +## 0. 类型声明(文档内统一使用) + +本文档中使用的类型说明: +- `String` = `XCEngine::Containers::String` +- `Array` = `XCEngine::Containers::Array` +- `HashMap` = `XCEngine::Containers::HashMap` +- `uint8/uint32/uint64` = `XCEngine::Core::uint8/uint32/uint64` +- `UniquePtr` = `XCEngine::Core::UniqueRef` 或 `std::unique_ptr` +- `SharedPtr` = `XCEngine::Core::Ref` 或 `std::shared_ptr` +- `Mutex` = `XCEngine::Threading::Mutex` +- `ITask` = `XCEngine::Threading::ITask` + +--- + +## 1. 概述 + +### 1.1 设计目标 + +资源系统是游戏引擎的核心基础设施之一,负责管理游戏运行时所需的所有数据资产。一个优秀的资源系统需要满足以下目标: + +#### 1.1.1 功能性目标 + +- **统一资源管理**:提供统一的接口来管理不同类型的资源(纹理、网格、材质、音频等) +- **异步加载支持**:支持后台线程异步加载资源,避免阻塞主线程 +- **资源缓存机制**:实现智能的资源缓存和淘汰策略,优化内存使用 +- **引用计数管理**:通过引用计数自动管理资源生命周期 +- **资源依赖管理**:跟踪资源之间的依赖关系,支持资源组加载和批量卸载 +- **可扩展架构**:易于添加新的资源类型和加载器 + +#### 1.1.2 性能目标 + +- **低内存占用**:通过LRU缓存和按需加载控制内存使用 +- **快速加载**:异步加载 + 缓存命中 = 零加载时间 +- **线程安全**:多线程环境下安全访问资源 +- **零拷贝优化**:尽可能减少不必要的数据拷贝 + +#### 1.1.3 开发效率目标 + +- **简单易用的API**:提供清晰的同步/异步加载接口 +- **灵活的配置**:支持自定义导入设置和加载选项 +- **完善的错误处理**:清晰的错误信息和调试支持 + +--- + +## 2. 系统架构 + +### 2.1 整体架构图 + +``` +┌─────────────────────────────────────────────────────────────────────────────────┐ +│ ResourceSystem │ +├─────────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌──────────────────────────────────────────────────────────────────────────┐ │ +│ │ 应用层 (Application) │ │ +│ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────────────┐ │ │ +│ │ │ Game Code │ │ Renderer │ │ Scene │ │ Editor │ │ │ +│ │ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ └─────────┬──────────┘ │ │ +│ └────────┼────────────────┼────────────────┼───────────────────┼────────────┘ │ +│ │ │ │ │ │ +│ ┌────────▼────────────────▼────────────────▼───────────────────▼────────────┐ │ +│ │ ResourceManager (资源管理器) │ │ +│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ +│ │ │ • Load(path) - 同步加载 │ │ │ +│ │ │ • LoadAsync(path, callback) - 异步加载 │ │ │ +│ │ │ • Unload(path/guid) - 卸载资源 │ │ │ +│ │ │ • RegisterLoader() - 注册加载器 │ │ │ +│ │ │ • AddRef/Release - 引用计数管理 │ │ │ +│ │ └─────────────────────────────────────────────────────────────────────┘ │ │ +│ └────────┬───────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌────────▼───────────────────────────────────────────────────────────────────┐ │ +│ │ ResourceLoader (加载器层) │ │ +│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │ │ +│ │ │TextureLoader │ │ MeshLoader │ │ AudioLoader │ │ShaderLoader │ │ │ +│ │ │ (纹理加载) │ │ (模型加载) │ │ (音频加载) │ │ (着色器加载) │ │ │ +│ │ └──────────────┘ └──────────────┘ └──────────────┘ └─────────────┘ │ │ +│ └────────┬───────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌────────▼───────────────────────────────────────────────────────────────────┐ │ +│ │ ResourceCache (缓存层) │ │ +│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ +│ │ │ • LRU淘汰策略 │ │ │ +│ │ │ • 内存压力响应 │ │ │ +│ │ │ • 手动刷新接口 │ │ │ +│ │ └─────────────────────────────────────────────────────────────────────┘ │ │ +│ └────────┬───────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌────────▼───────────────────────────────────────────────────────────────────┐ │ +│ │ AsyncLoader (异步加载层) │ │ +│ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ +│ │ │ • 后台工作线程 │ │ │ +│ │ │ • 任务队列管理 │ │ │ +│ │ │ • 完成回调分发 │ │ │ +│ │ └─────────────────────────────────────────────────────────────────────┘ │ │ +│ └────────┬───────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌────────▼───────────────────────────────────────────────────────────────────┐ │ +│ │ FileSystem (文件系统层) │ │ +│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ +│ │ │ Stream │ │ Path.h │ │ Archive │ │ Compression │ │ │ +│ │ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │ │ +│ └────────────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────────┘ +``` + +### 2.2 模块职责 + +| 模块 | 职责 | 关键类 | +|------|------|--------| +| **ResourceManager** | 资源总入口,引用计数管理 | ResourceManager | +| **ResourceLoader** | 具体资源类型的加载逻辑 | IResourceLoader, TextureLoader, MeshLoader | +| **ResourceCache** | 内存缓存,LRU淘汰 | ResourceCache, CacheEntry | +| **AsyncLoader** | 异步任务调度 | AsyncLoader, LoadRequest | +| **FileSystem** | 文件读写,路径管理 | FileSystem, Path, FileReader | + +### 2.3 数据流 + +``` +同步加载流程: + Load(path) → CheckCache → Found? → Return Handle + ↓ + Not Found + ↓ + GetLoader(type) → LoadResource → Create Handle → Add to Cache → Return + +异步加载流程: + LoadAsync(path, callback) → Create Request → Submit to Queue + ↓ + Worker Thread: Get Request → GetLoader → LoadResource + ↓ + Main Thread: Update() → Process Completed → Invoke Callback → Create Handle +``` + +--- + +## 3. 目录结构 + +### 3.1 设计目录结构 + +``` +engine/include/XCEngine/Resources/ +├── Resources.h # 主头文件,导出所有资源系统类 +├── IResource.h # 资源基类接口 +├── ResourceHandle.h # 资源句柄(模板智能指针) +├── ResourceManager.h # 资源管理器 +├── IResourceLoader.h # 加载器基类接口 +├── ResourceCache.h # 资源缓存 +├── AsyncLoader.h # 异步加载器 +├── ImportSettings.h # 导入设置基类 +│ +├── Texture.h # 纹理资源 +├── TextureLoader.h # 纹理加载器 +├── TextureImportSettings.h # 纹理导入设置 +│ +├── Mesh.h # 网格资源 +├── MeshLoader.h # 模型加载器 +├── MeshImportSettings.h # 模型导入设置 +│ +├── Material.h # 材质资源 +├── MaterialLoader.h # 材质加载器 +│ +├── Shader.h # 着色器资源 +├── ShaderLoader.h # 着色器加载器 +│ +├── AudioClip.h # 音频资源 +├── AudioLoader.h # 音频加载器 +│ +├── BinaryResource.h # 二进制资源 +└── ResourceTypes.h # 资源类型枚举 + +engine/src/Resources/ +├── Resources.cpp # 资源系统初始化 +├── ResourceManager.cpp +├── ResourceCache.cpp +├── AsyncLoader.cpp +├── TextureLoader.cpp +├── MeshLoader.cpp +├── MaterialLoader.cpp +├── ShaderLoader.cpp +└── AudioLoader.cpp +``` + +### 3.2 与现有项目整合 + +资源系统需要整合到现有项目中,需要创建或更新的文件: + +``` +engine/ +├── include/XCEngine/ +│ └── XCEngine.h # 添加 #include "Resources/Resources.h" +│ +└── src/ + └── Resources/ # 新建目录 + └── (上述实现文件) +``` + +--- + +## 4. 核心类型定义 + +### 4.1 资源类型枚举 + +```cpp +// ResourceTypes.h +namespace XCEngine { +namespace Resources { + +// 资源类型 +enum class ResourceType : Core::uint8 { + Unknown = 0, + Texture, + Mesh, + Material, + Shader, + AudioClip, + Binary, + AnimationClip, + Skeleton, + Font, + ParticleSystem, + Scene, + Prefab +}; + +constexpr const char* GetResourceTypeName(ResourceType type) { + switch (type) { + case ResourceType::Texture: return "Texture"; + case ResourceType::Mesh: return "Mesh"; + case ResourceType::Material: return "Material"; + case ResourceType::Shader: return "Shader"; + case ResourceType::AudioClip: return "AudioClip"; + case ResourceType::Binary: return "Binary"; + case ResourceType::AnimationClip: return "AnimationClip"; + case ResourceType::Skeleton: return "Skeleton"; + case ResourceType::Font: return "Font"; + case ResourceType::ParticleSystem:return "ParticleSystem"; + case ResourceType::Scene: return "Scene"; + case ResourceType::Prefab: return "Prefab"; + default: return "Unknown"; + } +} + +// 资源使用64位GUID作为唯一标识符 +// GUID生成规则:MD5(path) 的前64位 +// 这样可以保证相同路径生成相同的GUID +struct ResourceGUID { + Core::uint64 value; + + ResourceGUID() : value(0) {} + explicit ResourceGUID(Core::uint64 v) : value(v) {} + + bool IsValid() const { return value != 0; } + + bool operator==(const ResourceGUID& other) const { return value == other.value; } + bool operator!=(const ResourceGUID& other) const { return value != other.value; } + + // 从路径生成GUID + static ResourceGUID Generate(const char* path); + static ResourceGUID Generate(const String& path); + + String ToString() const; +}; + +// 全局函数 +inline ResourceGUID MakeResourceGUID(const char* path) { + return ResourceGUID::Generate(path); +} + +// 从模板类型获取ResourceType的辅助函数 +template +ResourceType GetResourceType(); + +// 特化模板 +template<> inline ResourceType GetResourceType() { return ResourceType::Texture; } +template<> inline ResourceType GetResourceType() { return ResourceType::Mesh; } +template<> inline ResourceType GetResourceType() { return ResourceType::Material; } +template<> inline ResourceType GetResourceType() { return ResourceType::Shader; } +template<> inline ResourceType GetResourceType() { return ResourceType::AudioClip; } +template<> inline ResourceType GetResourceType() { return ResourceType::Binary; } + +// 导入设置基类 +class ImportSettings { +public: + virtual ~ImportSettings() = default; + + // 克隆设置 + virtual UniquePtr Clone() const = 0; + + // 从JSON加载 + virtual bool LoadFromJSON(const String& json) { return false; } + + // 保存为JSON + virtual String SaveToJSON() const { return String(); } +}; + +} // namespace Resources +} // namespace XCEngine +} + +} // namespace Resources +} // namespace XCEngine +``` + +### 4.2 资源GUID + +```cpp +// 资源使用64位GUID作为唯一标识符 +// GUID生成规则:MD5(path) 的前64位 +// 这样可以保证相同路径生成相同的GUID + +struct ResourceGUID { + uint64 value; + + ResourceGUID() : value(0) {} + explicit ResourceGUID(uint64 v) : value(v) {} + + bool IsValid() const { return value != 0; } + + bool operator==(const ResourceGUID& other) const { return value == other.value; } + bool operator!=(const ResourceGUID& other) const { return value != other.value; } + + // 从路径生成GUID + static ResourceGUID Generate(const char* path); + static ResourceGUID Generate(const String& path); + + String ToString() const; +}; + +// 全局函数 +inline ResourceGUID MakeResourceGUID(const char* path) { + return ResourceGUID::Generate(path); +} +``` + +### 4.3 资源路径 + +```cpp +// 资源路径使用相对于资源根目录的路径 +// 例如:textures/player.png, models/player.fbx +// 资源系统会自动添加资源根目录前缀 + +class ResourcePath { +public: + ResourcePath() = default; + ResourcePath(const char* path); + ResourcePath(const String& path); + + // 获取扩展名 + String GetExtension() const; + + // 获取文件名(不含扩展名) + String GetStem() const; + + // 获取完整路径 + String GetFullPath() const; + + // 获取相对于资源根的路径 + String GetRelativePath() const; + + // 转换为资源GUID + ResourceGUID ToGUID() const; + + // 检查扩展名 + bool HasExtension(const char* ext) const; + bool HasAnyExtension(const char* const* extensions, Core::uint32 count) const; + +private: + String m_path; +}; +``` + +--- + +## 5. 核心接口设计 + +### 5.1 资源基类接口 (IResource) + +```cpp +// IResource.h +namespace XCEngine { +namespace Resources { + +class IResource { +public: + virtual ~IResource() = default; + + // 获取资源类型 + virtual ResourceType GetType() const = 0; + + // 获取资源名称 + virtual const String& GetName() const = 0; + + // 获取资源路径 + virtual const String& GetPath() const = 0; + + // 获取资源GUID + virtual ResourceGUID GetGUID() const = 0; + + // 资源是否有效 + virtual bool IsValid() const = 0; + + // 获取资源内存大小(用于缓存统计) + virtual size_t GetMemorySize() const = 0; + + // 释放资源(返回到对象池或真正删除) + virtual void Release() = 0; + +protected: + // 资源初始化(供子类调用) + struct ConstructParams { + String name; + String path; + ResourceGUID guid; + size_t memorySize = 0; + }; + + void Initialize(const ConstructParams& params) { + m_name = params.name; + m_path = params.path; + m_guid = params.guid; + m_memorySize = params.memorySize; + m_isValid = true; + } + + void SetInvalid() { m_isValid = false; } + + String m_name; + String m_path; + ResourceGUID m_guid; + bool m_isValid = false; + size_t m_memorySize = 0; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +### 5.2 资源句柄 (ResourceHandle) + +```cpp +// ResourceHandle.h +#include +#include + +namespace XCEngine { +namespace Resources { + +// 资源句柄模板类 +// 类似智能指针,但专门用于资源管理 +template +class ResourceHandle { + static_assert(std::is_base_of_v, "T must derive from IResource"); + +public: + ResourceHandle() = default; + + explicit ResourceHandle(T* resource) + : m_resource(resource) { + if (m_resource) { + ResourceManager::Get().AddRef(m_resource->GetGUID()); + } + } + + ResourceHandle(const ResourceHandle& other) + : m_resource(other.m_resource) { + if (m_resource) { + ResourceManager::Get().AddRef(m_resource->GetGUID()); + } + } + + ResourceHandle(ResourceHandle&& other) noexcept + : m_resource(other.m_resource) { + // 移动语义不转移引用计数所有权 + // 原句柄被掏空,不减少引用计数 + other.m_resource = nullptr; + } + + ~ResourceHandle() { + Reset(); + } + + ResourceHandle& operator=(const ResourceHandle& other) { + if (this != &other) { + Reset(); + m_resource = other.m_resource; + if (m_resource) { + ResourceManager::Get().AddRef(m_resource->GetGUID()); + } + } + return *this; + } + + ResourceHandle& operator=(ResourceHandle&& other) noexcept { + if (this != &other) { + // 先释放当前持有的资源 + Reset(); + // 移动所有权 + m_resource = other.m_resource; + // 原句柄被掏空,不减少引用计数 + other.m_resource = nullptr; + } + return *this; + } + + // 访问资源 + T* Get() const { return m_resource; } + T* operator->() const { return m_resource; } + T& operator*() const { return *m_resource; } + + // 检查有效性 + bool IsValid() const { return m_resource != nullptr && m_resource->IsValid(); } + explicit operator bool() const { return IsValid(); } + + // 获取GUID + ResourceGUID GetGUID() const { + return m_resource ? m_resource->GetGUID() : ResourceGUID(0); + } + + // 获取资源类型 + ResourceType GetResourceType() const { + return m_resource ? m_resource->GetType() : ResourceType::Unknown; + } + + // 重置句柄 + void Reset() { + if (m_resource) { + ResourceManager::Get().Release(m_resource->GetGUID()); + m_resource = nullptr; + } + } + + // 交换 + void Swap(ResourceHandle& other) { + std::swap(m_resource, other.m_resource); + } + +private: + T* m_resource = nullptr; +}; + +// 比较操作符 +template +bool operator==(const ResourceHandle& lhs, const ResourceHandle& rhs) { + return lhs.GetGUID() == rhs.GetGUID(); +} + +template +bool operator!=(const ResourceHandle& lhs, const ResourceHandle& rhs) { + return !(lhs == rhs); +} + +} // namespace Resources +} // namespace XCEngine +``` + +### 5.3 加载器基类接口 (IResourceLoader) + +```cpp +// IResourceLoader.h +namespace XCEngine { +namespace Resources { + +// 加载结果 +struct LoadResult { + IResource* resource = nullptr; + bool success = false; + String errorMessage; + + LoadResult() = default; + + explicit LoadResult(IResource* res) + : resource(res), success(res != nullptr) {} + + explicit LoadResult(const String& error) + : success(false), errorMessage(error) {} + + explicit LoadResult(bool success, const String& error = "") + : success(success), errorMessage(error) {} + + operator bool() const { return success && resource != nullptr; } +}; + +// 加载器接口 +class IResourceLoader { +public: + virtual ~IResourceLoader() = default; + + // 获取支持的资源类型 + virtual ResourceType GetResourceType() const = 0; + + // 获取支持的文件扩展名 + virtual Array GetSupportedExtensions() const = 0; + + // 检查是否可以加载该文件 + virtual bool CanLoad(const String& path) const = 0; + + // 同步加载 + virtual LoadResult Load(const String& path, const ImportSettings* settings = nullptr) = 0; + + // 异步加载(默认实现:同步加载然后在主线程回调) + virtual void LoadAsync(const String& path, + const ImportSettings* settings, + std::function callback) { + LoadResult result = Load(path, settings); + if (callback) { + callback(result); + } + } + + // 获取默认导入设置 + virtual ImportSettings* GetDefaultSettings() const = 0; + +protected: + // 辅助方法:从文件读取数据 + static Array ReadFileData(const String& path); + + // 辅助方法:解析路径获取扩展名 + static String GetExtension(const String& path); +}; + +// 加载器工厂宏(方便注册) +#define REGISTER_RESOURCE_LOADER(loaderType) \ + namespace { \ + struct loaderType##Registrar { \ + loaderType##Registrar() { \ + ResourceManager::Get().RegisterLoader(new loaderType()); \ + } \ + } g_##loaderType##Registrar; \ + } +} // namespace Resources +} // namespace XCEngine +``` + +### 5.4 资源管理器 (ResourceManager) + +```cpp +// ResourceManager.h +namespace XCEngine { +namespace Resources { + +class ResourceManager { +public: + static ResourceManager& Get(); + + // ==================== 初始化 ==================== + + void Initialize(); + void Shutdown(); + + // 设置资源根目录 + void SetResourceRoot(const String& rootPath); + const String& GetResourceRoot() const; + + // ==================== 同步加载 ==================== + + // 通过路径加载 + template + ResourceHandle Load(const String& path, ImportSettings* settings = nullptr) { + static_assert(std::is_base_of_v, "T must derive from IResource"); + + ResourcePath resourcePath(path); + ResourceGUID guid = resourcePath.ToGUID(); + + // 1. 检查缓存 + IResource* cached = FindInCache(guid); + if (cached) { + return ResourceHandle(static_cast(cached)); + } + + // 2. 查找加载器 + IResourceLoader* loader = FindLoader(GetResourceType()); + if (!loader) { + Debug::Logger::Get().Warning(Debug::LogCategory::FileSystem, + "No loader found for resource type: " + String(GetResourceTypeName(GetResourceType()))); + return ResourceHandle(); + } + + // 3. 加载资源 + LoadResult result = loader->Load(resourcePath.GetFullPath(), settings); + if (!result) { + Debug::Logger::Get().Error(Debug::LogCategory::FileSystem, + "Failed to load resource: " + path + " - " + result.errorMessage); + return ResourceHandle(); + } + + // 4. 添加到缓存 + AddToCache(guid, result.resource); + + return ResourceHandle(static_cast(result.resource)); + } + + // 通过GUID加载 + template + ResourceHandle Load(ResourceGUID guid) { + // 从GUID反向查找路径(需要维护guid到path的映射) + // 这里简化处理,实际实现需要从数据库查询 + return ResourceHandle(); + } + + // ==================== 异步加载 ==================== + + // 异步加载资源(需要显式指定类型) + void LoadAsync(const String& path, ResourceType type, + std::function callback); + + // 异步加载资源(带自定义设置) + void LoadAsync(const String& path, ResourceType type, ImportSettings* settings, + std::function callback); + + // ==================== 卸载 ==================== + + // 通过路径卸载 + void Unload(const String& path); + + // 通过GUID卸载 + void Unload(ResourceGUID guid); + + // 卸载所有未使用的资源 + void UnloadUnused(); + + // 卸载所有资源 + void UnloadAll(); + + // ==================== 引用计数 ==================== + + // 增加引用计数 + void AddRef(ResourceGUID guid); + + // 减少引用计数(引用计数为0时可能卸载资源) + void Release(ResourceGUID guid); + + // 获取引用计数 + Core::uint32 GetRefCount(ResourceGUID guid) const; + + // ==================== 加载器管理 ==================== + + // 注册加载器(ResourceManager拥有加载器) + void RegisterLoader(IResourceLoader* loader); + + // 移除加载器 + void UnregisterLoader(ResourceType type); + + // 获取加载器 + IResourceLoader* GetLoader(ResourceType type) const; + + // ==================== 缓存管理 ==================== + + // 设置内存预算(字节) + void SetMemoryBudget(size_t bytes); + + // 获取当前内存使用 + size_t GetMemoryUsage() const; + + // 获取内存预算 + size_t GetMemoryBudget() const; + + // 刷新缓存(强制淘汰最少使用的资源) + void FlushCache(); + + // ==================== 查询 ==================== + + // 查找资源(不增加引用计数) + IResource* Find(const String& path); + IResource* Find(ResourceGUID guid); + + // 检查资源是否存在 + bool Exists(const String& path) const; + bool Exists(ResourceGUID guid) const; + + // ==================== 资源根目录相关 ==================== + + // 解析资源路径(添加资源根目录) + String ResolvePath(const String& relativePath) const; + +private: + ResourceManager() = default; + ~ResourceManager() = default; + + // 内部方法 + IResource* FindInCache(ResourceGUID guid); + void AddToCache(ResourceGUID guid, IResource* resource); + IResourceLoader* FindLoader(ResourceType type); + void ReloadResource(ResourceGUID guid); + + // 数据成员 + String m_resourceRoot; + + // 资源缓存 + HashMap m_resourceCache; + + // 引用计数 + HashMap m_refCounts; + + // GUID到路径的映射(用于从guid加载) + HashMap m_guidToPath; + + // 加载器 + HashMap> m_loaders; + + // 缓存统计 + size_t m_memoryUsage = 0; + size_t m_memoryBudget = 512 * 1024 * 1024; // 默认512MB + + // 异步加载器 + UniquePtr m_asyncLoader; + + // 互斥锁 + Threading::Mutex m_mutex; + + friend class ResourceHandleBase; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +### 5.5 资源缓存 (ResourceCache) + +```cpp +// ResourceCache.h +#include + +namespace XCEngine { +namespace Resources { + +// 缓存条目 +struct CacheEntry { + IResource* resource; + ResourceGUID guid; + size_t memorySize; + Core::uint64 lastAccessTime; // 使用Profiler::Get().GetTickCount() + Core::uint32 accessCount; + + CacheEntry() + : resource(nullptr), memorySize(0), lastAccessTime(0), accessCount(0) {} + + CacheEntry(IResource* res, size_t size) + : resource(res), guid(res->GetGUID()), memorySize(size), + lastAccessTime(GetCurrentTick()), accessCount(1) {} + +private: + static Core::uint64 GetCurrentTick(); +}; + +// LRU缓存实现 +class ResourceCache { +public: + ResourceCache(); + ~ResourceCache(); + + // 添加资源到缓存 + void Add(ResourceGUID guid, IResource* resource); + + // 从缓存移除 + void Remove(ResourceGUID guid); + + // 查找资源(不移动到头部) + IResource* Find(ResourceGUID guid) const; + + // 访问资源(更新LRU信息) + void Touch(ResourceGUID guid); + + // 获取缓存大小 + size_t GetSize() const { return m_cache.Size(); } + + // 获取内存使用 + size_t GetMemoryUsage() const { return m_memoryUsage; } + + // 设置内存预算 + void SetMemoryBudget(size_t bytes); + size_t GetMemoryBudget() const { return m_memoryBudget; } + + // 内存压力响应(淘汰资源直到满足要求) + void OnMemoryPressure(size_t requiredBytes); + + // 引用计数为0时的通知(供ResourceManager调用) + void OnZeroRefCount(ResourceGUID guid); + + // 刷新缓存(淘汰所有未使用的资源) + void Flush(); + + // 清空缓存 + void Clear(); + + // 获取最少使用的资源(用于调试) + Array GetLRUList(size_t count) const; + +private: + // 淘汰最少使用的资源 + void Evict(size_t requiredBytes); + + // 更新内存统计 + void UpdateMemoryStats(); + + // 数据成员 + HashMap m_cache; + Array m_lruOrder; // 按访问时间排序,最少使用的在前面 + size_t m_memoryUsage = 0; + size_t m_memoryBudget = 512 * 1024 * 1024; // 默认512MB + + Mutex m_mutex; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +### 5.6 异步加载器 (AsyncLoader) + +```cpp +// AsyncLoader.h +#include +#include + +namespace XCEngine { +namespace Resources { + +// 加载请求 +struct LoadRequest { + String path; + ResourceType type; + std::function callback; + UniquePtr settings; + Core::uint64 requestId; + + LoadRequest() + : requestId(0) {} + + LoadRequest(const String& p, ResourceType t, + std::function cb, + ImportSettings* s = nullptr) + : path(p), type(t), callback(std::move(cb)), + settings(s), requestId(GenerateRequestId()) {} + +private: + static Core::uint64 GenerateRequestId(); +}; + +// 加载任务(工作线程执行) +class LoadTask : public Threading::ITask { +public: + LoadTask(LoadRequest request, IResourceLoader* loader); + + void Execute() override; + + LoadResult& GetResult() { return m_result; } + +private: + LoadRequest m_request; + IResourceLoader* m_loader; + LoadResult m_result; +}; + +// 异步加载器 +class AsyncLoader { +public: + static AsyncLoader& Get(); + + // 初始化 + void Initialize(Core::uint32 workerThreadCount = 2); + void Shutdown(); + + // 提交加载请求(需要显式指定类型) + void Submit(const String& path, ResourceType type, + std::function callback); + + // 提交加载请求(带自定义设置) + void Submit(const String& path, ResourceType type, ImportSettings* settings, + std::function callback); + + // 更新(每帧调用,处理完成的加载) + void Update(); + + // 检查是否正在加载 + bool IsLoading() const { return m_pendingCount > 0; } + + // 获取待处理数量 + Core::uint32 GetPendingCount() const { return m_pendingCount; } + + // 获取加载进度(0.0 - 1.0) + float GetProgress() const; + + // 取消所有待处理的请求 + void CancelAll(); + + // 取消特定请求 + void Cancel(Core::uint64 requestId); + +private: + AsyncLoader() = default; + ~AsyncLoader() = default; + + void SubmitInternal(LoadRequest& request); + + // 待处理的请求队列 + Threading::Mutex m_queueMutex; + Array m_pendingQueue; + + // 完成的请求队列(主线程处理) + Threading::Mutex m_completedMutex; + Array m_completedQueue; + + // 统计 + std::atomic m_pendingCount{0}; + std::atomic m_completedCount{0}; + Core::uint32 m_totalRequested = 0; + + // 加载器查找 + IResourceLoader* FindLoader(ResourceType type) const; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +--- + +## 6. 具体资源类型 + +### 6.1 纹理资源 (Texture) + +```cpp +// Texture.h +namespace XCEngine { +namespace Resources { + +// 纹理类型 +enum class TextureType { + Texture2D, + Texture3D, + TextureCube, + Texture2DArray, + TextureCubeArray +}; + +// 纹理格式 +enum class TextureFormat { + Unknown, + R8_UNORM, + RG8_UNORM, + RGBA8_UNORM, + RGBA8_SRGB, + R16_FLOAT, + RG16_FLOAT, + RGBA16_FLOAT, + R32_FLOAT, + RG32_FLOAT, + RGBA32_FLOAT, + D16_UNORM, + D24_UNORM_S8_UINT, + D32_FLOAT, + D32_FLOAT_S8_X24_UINT, + BC1_UNORM, + BC1_UNORM_SRGB, + BC2_UNORM, + BC2_UNORM_SRGB, + BC3_UNORM, + BC3_UNORM_SRGB, + BC4_UNORM, + BC5_UNORM, + BC6H_UF16, + BC7_UNORM, + BC7_UNORM_SRGB +}; + +// 纹理使用flags +enum class TextureUsage : Core::uint8 { + None = 0, + ShaderResource = 1 << 0, + RenderTarget = 1 << 1, + DepthStencil = 1 << 2, + UnorderedAccess = 1 << 3, + TransferSrc = 1 << 4, + TransferDst = 1 << 5 +}; + +// 纹理资源 +class Texture : public IResource { +public: + Texture(); + virtual ~Texture() override; + + // IResource 接口 + ResourceType GetType() const override { return ResourceType::Texture; } + const String& GetName() const override { return m_name; } + const String& GetPath() const override { return m_path; } + ResourceGUID GetGUID() const override { return m_guid; } + bool IsValid() const override { return m_isValid; } + size_t GetMemorySize() const override { return m_memorySize; } + void Release() override; + + // 纹理属性 + Core::uint32 GetWidth() const { return m_width; } + Core::uint32 GetHeight() const { return m_height; } + Core::uint32 GetDepth() const { return m_depth; } + Core::uint32 GetMipLevels() const { return m_mipLevels; } + Core::uint32 GetArraySize() const { return m_arraySize; } + TextureType GetTextureType() const { return m_textureType; } + TextureFormat GetFormat() const { return m_format; } + TextureUsage GetUsage() const { return m_usage; } + + // RHI资源 + class IRHIResource* GetRHIResource() const { return m_rhiResource; } + void SetRHIResource(class IRHIResource* resource); + + // 创建纹理(从原始数据) + bool Create(Core::uint32 width, Core::uint32 height, Core::uint32 depth, + Core::uint32 mipLevels, TextureType type, TextureFormat format, + const void* data, size_t dataSize); + + // 生成Mipmap + bool GenerateMipmaps(); + +private: + // 成员变量 + String m_name; + String m_path; + ResourceGUID m_guid; + bool m_isValid = false; + size_t m_memorySize = 0; + + Core::uint32 m_width = 0; + Core::uint32 m_height = 0; + Core::uint32 m_depth = 1; + Core::uint32 m_mipLevels = 1; + Core::uint32 m_arraySize = 1; + TextureType m_textureType = TextureType::Texture2D; + TextureFormat m_format = TextureFormat::RGBA8_UNORM; + TextureUsage m_usage = TextureUsage::ShaderResource; + + class IRHIResource* m_rhiResource = nullptr; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +### 6.2 纹理导入设置 + +```cpp +// TextureImportSettings.h +namespace XCEngine { +namespace Resources { + +class TextureImportSettings : public ImportSettings { +public: + TextureImportSettings(); + virtual ~TextureImportSettings() override; + + // ==================== 纹理设置 ==================== + + // 纹理类型 + void SetTextureType(TextureType type) { m_textureType = type; } + TextureType GetTextureType() const { return m_textureType; } + + // 目标格式(用于压缩) + void SetTargetFormat(TextureFormat format) { m_targetFormat = format; } + TextureFormat GetTargetFormat() const { return m_targetFormat; } + + // 是否生成Mipmap + void SetGenerateMipmaps(bool generate) { m_generateMipmaps = generate; } + bool GetGenerateMipmaps() const { return m_generateMipmaps; } + + // Mipmap过滤方式 + void SetMipmapFilter(MipmapFilter filter) { m_mipmapFilter = filter; } + MipmapFilter GetMipmapFilter() const { return m_mipmapFilter; } + + // 各向异性过滤 + void SetMaxAnisotropy(Core::uint32 anisotropy) { m_maxAnisotropy = anisotropy; } + Core::uint32 GetMaxAnisotropy() const { return m_maxAnisotropy; } + + // 是否sRGB(影响着色器中的采样) + void SetSRGB(bool srgb) { m_sRGB = srgb; } + bool GetSRGB() const { return m_sRGB; } + + // 是否启用纹理数组 + void SetTextureArray(bool array) { m_textureArray = array; } + bool GetTextureArray() const { return m_textureArray; } + + // 垂直翻转 + void SetFlipVertical(bool flip) { m_flipVertical = flip; } + bool GetFlipVertical() const { return m_flipVertical; } + + // 水平翻转 + void SetFlipHorizontal(bool flip) { m_flipHorizontal = flip; } + bool GetFlipHorizontal() const { return m_flipHorizontal; } + + // 边框颜色(对于透明纹理) + void SetBorderColor(const Math::Color& color) { m_borderColor = color; } + const Math::Color& GetBorderColor() const { return m_borderColor; } + + // ==================== 压缩设置 ==================== + + // 压缩质量 + void SetCompressionQuality(CompressionQuality quality) { m_compressionQuality = quality; } + CompressionQuality GetCompressionQuality() const { return m_compressionQuality; } + + // 是否使用硬件压缩 + void SetUseHardwareCompression(bool use) { m_useHardwareCompression = use; } + bool GetUseHardwareCompression() const { return m_useHardwareCompression; } + + // ==================== 实用方法 ==================== + + // 克隆设置 + UniquePtr Clone() const override; + + // 从JSON加载 + bool LoadFromJSON(const String& json); + + // 保存为JSON + String SaveToJSON() const; + +private: + // 成员变量 + TextureType m_textureType = TextureType::Texture2D; + TextureFormat m_targetFormat = TextureFormat::Unknown; // 自动选择 + bool m_generateMipmaps = true; + MipmapFilter m_mipmapFilter = MipmapFilter::Box; + Core::uint32 m_maxAnisotropy = 16; + bool m_sRGB = false; + bool m_textureArray = false; + bool m_flipVertical = false; + bool m_flipHorizontal = false; + Math::Color m_borderColor = Math::Color::Black; + CompressionQuality m_compressionQuality = CompressionQuality::High; + bool m_useHardwareCompression = true; +}; + +// Mipmap过滤方式 +enum class MipmapFilter { + Box, + Kaiser +}; + +// 压缩质量 +enum class CompressionQuality { + Low, + Medium, + High, + Ultra +}; + +} // namespace Resources +} // namespace XCEngine +``` + +### 6.3 纹理加载器 + +```cpp +// TextureLoader.h +namespace XCEngine { +namespace Resources { + +class TextureLoader : public IResourceLoader { +public: + TextureLoader(); + virtual ~TextureLoader() override; + + // IResourceLoader 接口 + ResourceType GetResourceType() const override { + return ResourceType::Texture; + } + + Array GetSupportedExtensions() const override { + return Array{".png", ".jpg", ".jpeg", ".tga", ".bmp", + ".dds", ".hdr", ".exr", ".psd"}; + } + + bool CanLoad(const String& path) const override { + String ext = GetExtension(path); + return ext == ".png" || ext == ".jpg" || ext == ".jpeg" || + ext == ".tga" || ext == ".bmp" || ext == ".dds" || + ext == ".hdr" || ext == ".exr" || ext == ".psd"; + } + + LoadResult Load(const String& path, const ImportSettings* settings = nullptr) override; + + ImportSettings* GetDefaultSettings() const override { + return new TextureImportSettings(); + } + +private: + // 内部加载方法 + LoadResult LoadPNG(const String& path, const TextureImportSettings* settings); + LoadResult LoadJPG(const String& path, const TextureImportSettings* settings); + LoadResult LoadTGA(const String& path, const TextureImportSettings* settings); + LoadResult LoadDDS(const String& path, const TextureImportSettings* settings); + LoadResult LoadHDR(const String& path, const TextureImportSettings* settings); + + // 辅助方法 + TextureFormat DetectFormat(const String& path) const; + bool ConvertFormat(const Core::uint8* srcData, Core::uint32 width, Core::uint32 height, + TextureFormat srcFormat, TextureFormat dstFormat, + Core::uint8*& outData, size_t& outDataSize); +}; + +// 注册加载器 +REGISTER_RESOURCE_LOADER(TextureLoader); + +} // namespace Resources +} // namespace XCEngine +``` + +### 6.4 网格资源 (Mesh) + +```cpp +// Mesh.h +namespace XCEngine { +namespace Resources { + +// 顶点属性 +enum class VertexAttribute : Core::uint32 { + Position = 1 << 0, + Normal = 1 << 1, + Tangent = 1 << 2, + Color = 1 << 3, + UV0 = 1 << 4, + UV1 = 1 << 5, + UV2 = 1 << 6, + UV3 = 1 << 7, + BoneWeights = 1 << 8, + BoneIndices = 1 << 9 +}; + +// 网格子资源(用于多材质) +struct MeshSection { + Core::uint32 baseVertex; + Core::uint32 vertexCount; + Core::uint32 startIndex; + Core::uint32 indexCount; + Core::uint32 materialID; + Math::AABB boundingBox; +}; + +// 网格资源 +class Mesh : public IResource { +public: + Mesh(); + virtual ~Mesh() override; + + // IResource 接口 + ResourceType GetType() const override { return ResourceType::Mesh; } + const String& GetName() const override { return m_name; } + const String& GetPath() const override { return m_path; } + ResourceGUID GetGUID() const override { return m_guid; } + bool IsValid() const override { return m_isValid; } + size_t GetMemorySize() const override { return m_memorySize; } + void Release() override; + + // ==================== 顶点数据 ==================== + + // 设置顶点数据 + void SetVertexData(const void* data, size_t size, Core::uint32 vertexCount, + Core::uint32 vertexStride, VertexAttribute attributes); + + // 获取顶点数据 + const void* GetVertexData() const { return m_vertexData.Data(); } + size_t GetVertexDataSize() const { return m_vertexData.Size(); } + Core::uint32 GetVertexCount() const { return m_vertexCount; } + Core::uint32 GetVertexStride() const { return m_vertexStride; } + VertexAttribute GetVertexAttributes() const { return m_attributes; } + + // ==================== 索引数据 ==================== + + // 设置索引数据 + void SetIndexData(const void* data, size_t size, Core::uint32 indexCount, bool use32Bit); + + // 获取索引数据 + const void* GetIndexData() const { return m_indexData.Data(); } + size_t GetIndexDataSize() const { return m_indexData.Size(); } + Core::uint32 GetIndexCount() const { return m_indexCount; } + bool IsUse32BitIndex() const { return m_use32BitIndex; } + + // ==================== 子网格 ==================== + + void AddSection(const MeshSection& section); + const Array& GetSections() const { return m_sections; } + + // ==================== 包围盒 ==================== + + void SetBoundingBox(const Math::AABB& box); + const Math::AABB& GetBoundingBox() const { return m_boundingBox; } + + // ==================== 骨骼动画(可选)==================== + + void SetSkeleton(class Skeleton* skeleton); + class Skeleton* GetSkeleton() const { return m_skeleton; } + + // ==================== RHI资源 ==================== + + class IRHIBuffer* GetVertexBuffer() const { return m_vertexBuffer; } + class IRHIBuffer* GetIndexBuffer() const { return m_indexBuffer; } + void SetRHIBuffers(class IRHIBuffer* vb, class IRHIBuffer* ib); + +private: + // 成员变量 + String m_name; + String m_path; + ResourceGUID m_guid; + bool m_isValid = false; + size_t m_memorySize = 0; + + // 顶点数据 + Array m_vertexData; + Core::uint32 m_vertexCount = 0; + Core::uint32 m_vertexStride = 0; + VertexAttribute m_attributes = VertexAttribute::Position; + + // 索引数据 + Array m_indexData; + Core::uint32 m_indexCount = 0; + bool m_use32BitIndex = false; + + // 子网格 + Array m_sections; + + // 包围盒 + Math::AABB m_boundingBox; + + // 骨骼 + class Skeleton* m_skeleton = nullptr; + + // RHI资源 + class IRHIBuffer* m_vertexBuffer = nullptr; + class IRHIBuffer* m_indexBuffer = nullptr; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +### 6.5 材质资源 (Material) + +```cpp +// Material.h +namespace XCEngine { +namespace Resources { + +// 材质属性类型 +enum class MaterialPropertyType { + Float, + Float2, + Float3, + Float4, + Int, + Int2, + Int3, + Int4, + Bool, + Texture, + Cubemap +}; + +// 材质属性 +struct MaterialProperty { + String name; + MaterialPropertyType type; + + // 值联合体 + union Value { + float floatValue[4]; + Core::int32 intValue[4]; + bool boolValue; + ResourceHandle textureValue; + + Value() { memset(this, 0, sizeof(Value)); } + } value; + + // 引用计数(纹理资源需要特殊处理) + Core::uint32 refCount; +}; + +// 材质资源 +class Material : public IResource { +public: + Material(); + virtual ~Material() override; + + // IResource 接口 + ResourceType GetType() const override { return ResourceType::Material; } + const String& GetName() const override { return m_name; } + const String& GetPath() const override { return m_path; } + ResourceGUID GetGUID() const override { return m_guid; } + bool IsValid() const override { return m_isValid; } + size_t GetMemorySize() const override { return m_memorySize; } + void Release() override; + + // ==================== 着色器 ==================== + + void SetShader(const ResourceHandle& shader); + class Shader* GetShader() const { return m_shader.Get(); } + + // ==================== 属性设置 ==================== + + void SetFloat(const String& name, float value); + void SetFloat2(const String& name, const Math::Vector2& value); + void SetFloat3(const String& name, const Math::Vector3& value); + void SetFloat4(const String& name, const Math::Vector4& value); + void SetInt(const String& name, int32 value); + void SetInt2(const String& name, const Math::IntVector2& value); + void SetInt3(const String& name, const Math::IntVector3& value); + void SetInt4(const String& name, const Math::IntVector4& value); + void SetBool(const String& name, bool value); + void SetTexture(const String& name, const ResourceHandle& texture); + + // ==================== 属性获取 ==================== + + float GetFloat(const String& name) const; + Math::Vector2 GetFloat2(const String& name) const; + // ... 其他Get方法 + + ResourceHandle GetTexture(const String& name) const; + + // ==================== 属性遍历 ==================== + + using PropertyIterator = HashMap::Iterator; + PropertyIterator BeginProperties() { return m_properties.Begin(); } + PropertyIterator EndProperties() { return m_properties.End(); } + + // ==================== 批处理数据 ==================== + + // 获取用于GPU的常数缓冲区数据 + const Array& GetConstantBufferData() const { return m_constantBufferData; } + + // 更新常数缓冲区(当属性变化时调用) + void UpdateConstantBuffer(); + +private: + // 成员变量 + String m_name; + String m_path; + ResourceGUID m_guid; + bool m_isValid = false; + size_t m_memorySize = 0; + + // 着色器 + ResourceHandle m_shader; + + // 属性表 + HashMap m_properties; + + // 常数缓冲区数据 + Array m_constantBufferData; + + // 纹理绑定信息(用于设置到Pipeline) + struct TextureBinding { + String name; + Core::uint32 slot; + ResourceHandle texture; + }; + Array m_textureBindings; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +### 6.6 音频资源 (AudioClip) + +```cpp +// AudioClip.h +namespace XCEngine { +namespace Resources { + +// 音频格式 +enum class AudioFormat { + Unknown, + WAV, + OGG, + MP3, + FLAC +}; + +// 音频类型 +enum class AudioType { + SFX, // 音效 + Music, // 背景音乐 + Voice // 语音 +}; + +// 音频资源 +class AudioClip : public IResource { +public: + AudioClip(); + virtual ~AudioClip() override; + + // IResource 接口 + ResourceType GetType() const override { return ResourceType::AudioClip; } + const String& GetName() const override { return m_name; } + const String& GetPath() const override { return m_path; } + ResourceGUID GetGUID() const override { return m_guid; } + bool IsValid() const override { return m_isValid; } + size_t GetMemorySize() const override { return m_memorySize; } + void Release() override; + + // ==================== 音频属性 ==================== + + // 采样率 + Core::uint32 GetSampleRate() const { return m_sampleRate; } + + // 通道数 + Core::uint32 GetChannels() const { return m_channels; } + + // 位深度 + Core::uint32 GetBitsPerSample() const { return m_bitsPerSample; } + + // 持续时间(秒) + float GetDuration() const { return m_duration; } + + // 数据大小 + size_t GetDataSize() const { return m_data.Size(); } + + // 格式 + AudioFormat GetFormat() const { return m_format; } + + // 类型 + AudioType GetAudioType() const { return m_audioType; } + + // ==================== 音频数据 ==================== + + // 获取PCM数据 + const Core::uint8* GetData() const { return m_data.Data(); } + + // 是否流式(不加载到内存) + bool IsStreaming() const { return m_isStreaming; } + + // 设置流式 + void SetStreaming(bool streaming) { m_isStreaming = streaming; } + + // ==================== 播放控制 ==================== + + // 创建音频源(用于播放) + class IAudioSource* CreateSource() const; + +private: + // 成员变量 + String m_name; + String m_path; + ResourceGUID m_guid; + bool m_isValid = false; + size_t m_memorySize = 0; + + // 音频属性 + Core::uint32 m_sampleRate = 0; + Core::uint32 m_channels = 0; + Core::uint32 m_bitsPerSample = 0; + float m_duration = 0.0f; + AudioFormat m_format = AudioFormat::Unknown; + AudioType m_audioType = AudioType::SFX; + bool m_isStreaming = false; + + // 音频数据 + Array m_data; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +--- + +## 7. 文件系统集成 + +### 7.1 文件系统接口 + +```cpp +// FileSystem.h (扩展现有IO模块) +namespace XCEngine { +namespace IO { + +// 文件系统接口 +class IFileSystem { +public: + virtual ~IFileSystem() = default; + + // 文件操作 + virtual bool FileExists(const String& path) const = 0; + virtual bool DirectoryExists(const String& path) const = 0; + + virtual size_t GetFileSize(const String& path) const = 0; + virtual bool GetFileTime(const String& path, Core::uint64& outTime) const = 0; + + // 读取 + virtual Array ReadAllBytes(const String& path) const = 0; + virtual String ReadAllText(const String& path) const = 0; + virtual bool Read(const String& path, void* buffer, size_t size, size_t offset = 0) const = 0; + + // 写入 + virtual bool WriteAllBytes(const String& path, const void* data, size_t size) = 0; + virtual bool WriteAllText(const String& path, const String& text) = 0; + virtual bool Write(const String& path, const void* data, size_t size, size_t offset = 0) = 0; + + // 目录操作 + virtual bool CreateDirectory(const String& path) = 0; + virtual bool DeleteDirectory(const String& path, bool recursive = false) = 0; + virtual bool DeleteFile(const String& path) = 0; + + // 遍历 + virtual void EnumerateFiles(const String& path, const String& pattern, + Array& outFiles) const = 0; + virtual void EnumerateDirectories(const String& path, const String& pattern, + Array& outDirectories) const = 0; + + // 获取路径信息 + virtual String GetExtension(const String& path) const = 0; + virtual String GetFileName(const String& path) const = 0; + virtual String GetFileNameWithoutExtension(const String& path) const = 0; + virtual String GetDirectoryName(const String& path) const = 0; + virtual String GetFullPath(const String& path) const = 0; + virtual String Combine(const String& path1, const String& path2) const = 0; +}; + +// 获取文件系统单例 +IFileSystem* GetFileSystem(); +void SetFileSystem(IFileSystem* fs); + +// Windows文件系统实现(默认) +class WindowsFileSystem : public IFileSystem { +public: + // 实现Windows API调用 +}; + +} // namespace IO +} // namespace XCEngine +``` + +### 7.2 资源文件系统 (ResourceFileSystem) + +```cpp +// ResourceFileSystem.h +namespace XCEngine { +namespace Resources { + +// 资源文件系统 - 管理资源包/归档 +class ResourceFileSystem { +public: + ResourceFileSystem(); + ~ResourceFileSystem(); + + // 初始化 + void Initialize(const String& rootPath); + void Shutdown(); + + // 添加资源包 + bool AddArchive(const String& archivePath); + bool AddDirectory(const String& directoryPath); + + // 移除资源包 + void RemoveArchive(const String& archivePath); + + // 查找资源 + bool FindResource(const String& relativePath, String& outAbsolutePath) const; + + // 读取资源数据 + Array ReadResource(const String& relativePath) const; + + // 检查资源是否存在 + bool Exists(const String& relativePath) const; + + // 获取资源信息 + struct ResourceInfo { + String path; + size_t size; + Core::uint64 modifiedTime; + bool inArchive; + String archivePath; + }; + + bool GetResourceInfo(const String& relativePath, ResourceInfo& outInfo) const; + + // 枚举资源 + void EnumerateResources(const String& pattern, Array& outResources) const; + +private: + // 资源包接口 + class IArchive { + public: + virtual ~IArchive() = default; + virtual bool Open(const String& path) = 0; + virtual void Close() = 0; + virtual bool Read(const String& fileName, void* buffer, size_t size, size_t offset) const = 0; + virtual size_t GetSize(const String& fileName) const = 0; + virtual bool Exists(const String& fileName) const = 0; + virtual void Enumerate(const String& pattern, Array& outFiles) const = 0; + }; + + // 数据成员 + String m_rootPath; + Array> m_archives; + Array m_directories; + + // 缓存 + mutable HashMap m_infoCache; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +--- + +## 8. 资源打包系统 + +### 8.1 资源包格式 + +``` +┌─────────────────────────────────────────────────────┐ +│ ResourcePackage │ +├─────────────────────────────────────────────────────┤ +│ Header (固定大小) │ +│ ├── Magic: "XCRP" (4 bytes) │ +│ ├── Version: uint16 │ +│ ├── Manifest Size: uint32 │ +│ ├── Asset Count: uint32 │ +│ └── Data Offset: uint64 │ +├─────────────────────────────────────────────────────┤ +│ Manifest (JSON/二进制) │ +│ ├── File 1: { path, offset, size, checksum } │ +│ ├── File 2: { path, offset, size, checksum } │ +│ └── ... │ +├─────────────────────────────────────────────────────┤ +│ Data Section │ +│ ├── File 1 Data (对齐到16字节) │ +│ ├── File 2 Data │ +│ └── ... │ +└─────────────────────────────────────────────────────┘ +``` + +### 8.2 资源包构建器 + +```cpp +// ResourcePackageBuilder.h +namespace XCEngine { +namespace Resources { + +class ResourcePackageBuilder { +public: + ResourcePackageBuilder(); + ~ResourcePackageBuilder(); + + // 添加文件 + bool AddFile(const String& sourcePath, const String& relativePath); + + // 添加目录 + bool AddDirectory(const String& sourceDir, const String& relativeBase = ""); + + // 设置输出路径 + void SetOutputPath(const String& path) { m_outputPath = path; } + + // 构建包 + bool Build(); + + // 获取进度 + float GetProgress() const { return m_progress; } + + // 获取错误信息 + const String& GetError() const { return m_error; } + +private: + // 文件条目 + struct FileEntry { + String sourcePath; + String relativePath; + size_t size; + uint64 checksum; + }; + + // 成员变量 + String m_outputPath; + Array m_files; + float m_progress = 0.0f; + String m_error; + + // 辅助方法 + Core::uint64 CalculateChecksum(const void* data, size_t size); + bool WriteHeader(FileWriter& writer, size_t dataOffset); + bool WriteManifest(FileWriter& writer); + bool WriteData(FileWriter& writer); +}; + +} // namespace Resources +} // namespace XCEngine +``` + +--- + +## 9. 资源依赖管理 + +### 9.1 依赖图 + +```cpp +// ResourceDependencyGraph.h +namespace XCEngine { +namespace Resources { + +// 资源依赖节点 +struct DependencyNode { + ResourceGUID guid; + ResourceType type; + Array dependencies; // 当前资源依赖的资源 + Array dependents; // 依赖当前资源的资源 + Core::uint32 refCount = 0; +}; + +// 依赖图 +class ResourceDependencyGraph { +public: + ResourceDependencyGraph(); + ~ResourceDependencyGraph(); + + // 添加节点 + void AddNode(ResourceGUID guid, ResourceType type); + + // 添加依赖关系 + void AddDependency(ResourceGUID owner, ResourceGUID dependency); + + // 移除节点 + void RemoveNode(ResourceGUID guid); + + // 移除依赖关系 + void RemoveDependency(ResourceGUID owner, ResourceGUID dependency); + + // 获取依赖(当前资源依赖的资源) + Array GetDependencies(ResourceGUID guid) const; + + // 获取依赖者(依赖当前资源的资源) + Array GetDependents(ResourceGUID guid) const; + + // 获取传递依赖(所有层级的依赖) + Array GetAllDependencies(ResourceGUID guid) const; + + // 引用计数管理 + void IncrementRefCount(ResourceGUID guid); + void DecrementRefCount(ResourceGUID guid); + Core::uint32 GetRefCount(ResourceGUID guid) const; + + // 查找循环依赖 + bool HasCircularDependency(ResourceGUID guid, Array& outCycle) const; + + // 拓扑排序(用于加载顺序) + Array TopologicalSort() const; + + // 加载资源组及其所有依赖 + Array LoadWithDependencies(const String& entryPath); + + // 卸载资源组(仅当没有依赖者时) + bool Unload(ResourceGUID guid); + +private: + HashMap m_nodes; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +--- + +## 10. 实现顺序 + +### 10.1 阶段划分 + +``` +阶段 4.1: 基础框架 (3天) + ├── 4.1.1 ResourceTypes.h - 资源类型枚举 + ├── 4.1.2 IResource.h - 资源基类接口 + ├── 4.1.3 ResourceHandle.h - 资源句柄 + ├── 4.1.4 IResourceLoader.h - 加载器接口 + └── 4.1.5 ResourceManager.h/cpp - 资源管理器基础 + +阶段 4.2: 缓存系统 (2天) + ├── 4.2.1 ResourceCache.h/cpp - LRU缓存实现 + └── 4.2.2 与ResourceManager集成 + +阶段 4.3: 异步加载 (2天) + ├── 4.3.1 AsyncLoader.h/cpp - 异步加载器 + ├── 4.3.2 与TaskSystem集成 + └── 4.3.3 完成回调机制 + +阶段 4.4: 具体资源类型 (4天) + ├── 4.4.1 Texture + TextureLoader - 纹理资源 + ├── 4.4.2 Mesh + MeshLoader - 网格资源 + ├── 4.4.3 Material + MaterialLoader - 材质资源 + └── 4.4.4 AudioClip + AudioLoader - 音频资源 + +阶段 4.5: 文件系统集成 (2天) + ├── 4.5.1 ResourceFileSystem - 资源文件系统 + └── 4.5.2 资源包支持 + +阶段 4.6: 依赖管理 (2天) + ├── 4.6.1 ResourceDependencyGraph - 依赖图 + └── 4.6.2 资源组加载/卸载 + +阶段 4.7: 测试与集成 (2天) + ├── 4.7.1 单元测试 + └── 4.7.2 与现有mvs集成 +``` + +### 10.2 详细任务列表 + +``` +任务 4.1.1: ResourceTypes.h + 实现: + - ResourceType 枚举(Texture, Mesh, Material, Shader, AudioClip等) + - GetResourceTypeName() 函数 + - ResourceGUID 结构体 + +任务 4.1.2: IResource.h + 实现: + - IResource 抽象基类 + - 纯虚方法:GetType(), GetName(), GetPath(), GetGUID(), IsValid(), GetMemorySize(), Release() + - 虚析构函数 + +任务 4.1.3: ResourceHandle.h + 实现: + - ResourceHandle 模板类 + - 构造/析构(自动引用计数) + - operator->(), Get(), IsValid() + - 移动语义支持 + +任务 4.1.4: IResourceLoader.h + 实现: + - IResourceLoader 抽象基类 + - LoadResult 结构体 + - GetResourceType(), GetSupportedExtensions(), CanLoad(), Load() + - REGISTER_RESOURCE_LOADER 宏 + +任务 4.1.5: ResourceManager.h/cpp + 实现: + - ResourceManager 单例 + - Initialize()/Shutdown() + - Load(path) 模板方法 + - Unload(path/guid) + - AddRef()/Release() + - RegisterLoader() + - SetMemoryBudget() + +任务 4.2.1: ResourceCache.h/cpp + 实现: + - CacheEntry 结构体 + - ResourceCache 类 + - Add(), Remove(), Find(), Touch() + - SetMemoryBudget(), OnMemoryPressure() + - LRU淘汰逻辑 + +任务 4.3.1: AsyncLoader.h/cpp + 实现: + - LoadRequest 结构体 + - AsyncLoader 单例 + - Submit(path, callback) + - Update() - 处理完成队列 + - IsLoading(), GetProgress() + +任务 4.4.1: Texture + TextureLoader + 实现: + - Texture 类(继承IResource) + - TextureImportSettings 类 + - TextureLoader 类(继承IResourceLoader) + - 使用stb_image加载PNG/JPG/TGA + - REGISTER_RESOURCE_LOADER(TextureLoader) + +任务 4.4.2: Mesh + MeshLoader + 实现: + - Mesh 类(继承IResource) + - MeshSection 结构体 + - MeshImportSettings 类 + - MeshLoader 类(使用Assimp) + - 支持OBJ/glTF格式 + - REGISTER_RESOURCE_LOADER(MeshLoader) + +任务 4.4.3: Material + MaterialLoader + 实现: + - Material 类 + - MaterialProperty 结构体 + - MaterialLoader 类(解析JSON格式) + - REGISTER_RESOURCE_LOADER(MaterialLoader) + +任务 4.4.4: AudioClip + AudioLoader + 实现: + - AudioClip 类 + - AudioLoader 类 + - 支持WAV格式 + - REGISTER_RESOURCE_LOADER(AudioLoader) + +任务 4.5.1: ResourceFileSystem + 实现: + - ResourceFileSystem 类 + - IArchive 接口 + - AddArchive(), AddDirectory() + - ReadResource(), Exists() + +任务 4.6.1: ResourceDependencyGraph + 实现: + - DependencyNode 结构体 + - ResourceDependencyGraph 类 + - AddDependency(), RemoveDependency() + - GetDependencies(), GetDependents() + - TopologicalSort() +``` + +--- + +## 11. 详细执行计划 + +> 本节详细说明如何逐步实现资源系统,包括每个文件的具体内容、实现步骤、测试方法和集成要点。 + +### 11.1 文件创建清单 + +首先,需要创建以下目录结构和文件: + +``` +engine/include/XCEngine/Resources/ +├── Resources.h # 主头文件 +├── ResourceTypes.h # 资源类型枚举 +├── ImportSettings.h # 导入设置基类 +├── IResource.h # 资源基类接口 +├── ResourceHandle.h # 资源句柄 +├── ResourceManager.h # 资源管理器 +├── IResourceLoader.h # 加载器基类 +├── ResourceCache.h # 资源缓存 +├── AsyncLoader.h # 异步加载器 +├── Texture.h # 纹理资源 +├── TextureLoader.h # 纹理加载器 +├── TextureImportSettings.h # 纹理导入设置 +├── Mesh.h # 网格资源 +├── MeshLoader.h # 网格加载器 +├── MeshImportSettings.h # 网格导入设置 +├── Material.h # 材质资源 +├── MaterialLoader.h # 材质加载器 +├── Shader.h # 着色器资源 +├── ShaderLoader.h # 着色器加载器 +├── AudioClip.h # 音频资源 +├── AudioLoader.h # 音频加载器 +└── BinaryResource.h # 二进制资源 + +engine/src/Resources/ +├── Resources.cpp # 资源系统初始化 +├── ResourceManager.cpp # 资源管理器实现 +├── ResourceCache.cpp # 缓存实现 +├── AsyncLoader.cpp # 异步加载实现 +├── TextureLoader.cpp # 纹理加载实现 +├── MeshLoader.cpp # 网格加载实现 +├── MaterialLoader.cpp # 材质加载实现 +├── ShaderLoader.cpp # 着色器加载实现 +└── AudioLoader.cpp # 音频加载实现 +``` + +### 11.2 第一阶段:基础框架(天1-3) + +#### 步骤 11.2.1 创建主头文件 Resources.h + +```cpp +// Resources.h +#pragma once + +#include "ResourceTypes.h" +#include "ImportSettings.h" +#include "IResource.h" +#include "ResourceHandle.h" +#include "ResourceManager.h" +#include "IResourceLoader.h" +#include "ResourceCache.h" +#include "AsyncLoader.h" + +// 具体资源类型 +#include "Texture.h" +#include "TextureLoader.h" +#include "TextureImportSettings.h" +#include "Mesh.h" +#include "MeshLoader.h" +#include "MeshImportSettings.h" +#include "Material.h" +#include "MaterialLoader.h" +#include "Shader.h" +#include "ShaderLoader.h" +#include "AudioClip.h" +#include "AudioLoader.h" +#include "BinaryResource.h" +``` + +#### 步骤 11.2.2 实现 ResourceTypes.h + +**文件**: `engine/include/XCEngine/Resources/ResourceTypes.h` + +```cpp +#pragma once +#include "../Core/Types.h" +#include "../Containers/String.h" +#include "../Containers/Array.h" +#include + +namespace XCEngine { +namespace Resources { + +// 资源类型枚举 +enum class ResourceType : Core::uint8 { + Unknown = 0, + Texture, + Mesh, + Material, + Shader, + AudioClip, + Binary, + AnimationClip, + Skeleton, + Font, + ParticleSystem, + Scene, + Prefab +}; + +constexpr const char* GetResourceTypeName(ResourceType type) { + switch (type) { + case ResourceType::Texture: return "Texture"; + case ResourceType::Mesh: return "Mesh"; + case ResourceType::Material: return "Material"; + case ResourceType::Shader: return "Shader"; + case ResourceType::AudioClip: return "AudioClip"; + case ResourceType::Binary: return "Binary"; + case ResourceType::AnimationClip: return "AnimationClip"; + case ResourceType::Skeleton: return "Skeleton"; + case ResourceType::Font: return "Font"; + case ResourceType::ParticleSystem:return "ParticleSystem"; + case ResourceType::Scene: return "Scene"; + case ResourceType::Prefab: return "Prefab"; + default: return "Unknown"; + } +} + +// ResourceGUID - 64位唯一标识符 +struct ResourceGUID { + Core::uint64 value; + + ResourceGUID() : value(0) {} + explicit ResourceGUID(Core::uint64 v) : value(v) {} + + bool IsValid() const { return value != 0; } + + bool operator==(const ResourceGUID& other) const { return value == other.value; } + bool operator!=(const ResourceGUID& other) const { return value != other.value; } + + static ResourceGUID Generate(const char* path); + static ResourceGUID Generate(const Containers::String& path); + + Containers::String ToString() const; +}; + +inline ResourceGUID MakeResourceGUID(const char* path) { + return ResourceGUID::Generate(path); +} + +// 模板特化获取ResourceType +template +ResourceType GetResourceType(); + +template<> inline ResourceType GetResourceType() { return ResourceType::Texture; } +template<> inline ResourceType GetResourceType() { return ResourceType::Mesh; } +template<> inline ResourceType GetResourceType() { return ResourceType::Material; } +template<> inline ResourceType GetResourceType() { return ResourceType::Shader; } +template<> inline ResourceType GetResourceType() { return ResourceType::AudioClip; } +template<> inline ResourceType GetResourceType() { return ResourceType::Binary; } + +// 导入设置基类 +class ImportSettings { +public: + virtual ~ImportSettings() = default; + + virtual UniquePtr Clone() const = 0; + virtual bool LoadFromJSON(const Containers::String& json) { return false; } + virtual Containers::String SaveToJSON() const { return Containers::String(); } +}; + +} // namespace Resources +} // namespace XCEngine +``` + +**实现文件** `engine/src/Resources/ResourceTypes.cpp`: +```cpp +#include "Resources/ResourceTypes.h" +#include + +namespace XCEngine { +namespace Resources { + +// 简单哈希实现(实际项目中可使用MD5) +ResourceGUID ResourceGUID::Generate(const char* path) { + Core::uint64 hash = 14695981039346656037ULL; // FNV offset basis + + while (*path) { + hash ^= static_cast(*path); + hash *= 1099511628211ULL; // FNV prime + path++; + } + + return ResourceGUID(hash); +} + +ResourceGUID ResourceGUID::Generate(const Containers::String& path) { + return Generate(path.CStr()); +} + +Containers::String ResourceGUID::ToString() const { + char buffer[17]; + snprintf(buffer, sizeof(buffer), "%016llx", value); + return Containers::String(buffer); +} + +} // namespace Resources +} // namespace XCEngine +``` + +#### 步骤 11.2.3 实现 IResource.h + +**文件**: `engine/include/XCEngine/Resources/IResource.h` + +```cpp +#pragma once +#include "ResourceTypes.h" +#include "../Containers/String.h" + +namespace XCEngine { +namespace Resources { + +class IResource { +public: + virtual ~IResource() = default; + + virtual ResourceType GetType() const = 0; + virtual const Containers::String& GetName() const = 0; + virtual const Containers::String& GetPath() const = 0; + virtual ResourceGUID GetGUID() const = 0; + virtual bool IsValid() const = 0; + virtual size_t GetMemorySize() const = 0; + virtual void Release() = 0; + +protected: + struct ConstructParams { + Containers::String name; + Containers::String path; + ResourceGUID guid; + size_t memorySize = 0; + }; + + void Initialize(const ConstructParams& params) { + m_name = params.name; + m_path = params.path; + m_guid = params.guid; + m_memorySize = params.memorySize; + m_isValid = true; + } + + void SetInvalid() { m_isValid = false; } + + Containers::String m_name; + Containers::String m_path; + ResourceGUID m_guid; + bool m_isValid = false; + size_t m_memorySize = 0; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +#### 步骤 11.2.4 实现 ResourceHandle.h + +**文件**: `engine/include/XCEngine/Resources/ResourceHandle.h` + +```cpp +#pragma once +#include "IResource.h" +#include +#include + +namespace XCEngine { +namespace Resources { + +template +class ResourceHandle { + static_assert(std::is_base_of_v, "T must derive from IResource"); + +public: + ResourceHandle() = default; + + explicit ResourceHandle(T* resource) + : m_resource(resource) { + if (m_resource) { + ResourceManager::Get().AddRef(m_resource->GetGUID()); + } + } + + ResourceHandle(const ResourceHandle& other) + : m_resource(other.m_resource) { + if (m_resource) { + ResourceManager::Get().AddRef(m_resource->GetGUID()); + } + } + + ResourceHandle(ResourceHandle&& other) noexcept + : m_resource(other.m_resource) { + other.m_resource = nullptr; + } + + ~ResourceHandle() { + Reset(); + } + + ResourceHandle& operator=(const ResourceHandle& other) { + if (this != &other) { + Reset(); + m_resource = other.m_resource; + if (m_resource) { + ResourceManager::Get().AddRef(m_resource->GetGUID()); + } + } + return *this; + } + + ResourceHandle& operator=(ResourceHandle&& other) noexcept { + if (this != &other) { + Reset(); + m_resource = other.m_resource; + other.m_resource = nullptr; + } + return *this; + } + + T* Get() const { return m_resource; } + T* operator->() const { return m_resource; } + T& operator*() const { return *m_resource; } + + bool IsValid() const { return m_resource != nullptr && m_resource->IsValid(); } + explicit operator bool() const { return IsValid(); } + + ResourceGUID GetGUID() const { + return m_resource ? m_resource->GetGUID() : ResourceGUID(0); + } + + ResourceType GetResourceType() const { + return m_resource ? m_resource->GetType() : ResourceType::Unknown; + } + + void Reset() { + if (m_resource) { + ResourceManager::Get().Release(m_resource->GetGUID()); + m_resource = nullptr; + } + } + + void Swap(ResourceHandle& other) { + std::swap(m_resource, other.m_resource); + } + +private: + T* m_resource = nullptr; +}; + +template +bool operator==(const ResourceHandle& lhs, const ResourceHandle& rhs) { + return lhs.GetGUID() == rhs.GetGUID(); +} + +template +bool operator!=(const ResourceHandle& lhs, const ResourceHandle& rhs) { + return !(lhs == rhs); +} + +} // namespace Resources +} // namespace XCEngine +``` + +#### 步骤 11.2.5 实现 IResourceLoader.h + +**文件**: `engine/include/XCEngine/Resources/IResourceLoader.h` + +```cpp +#pragma once +#include "IResource.h" +#include "ResourceTypes.h" +#include "../Containers/String.h" +#include "../Containers/Array.h" +#include + +namespace XCEngine { +namespace Resources { + +struct LoadResult { + IResource* resource = nullptr; + bool success = false; + Containers::String errorMessage; + + LoadResult() = default; + explicit LoadResult(IResource* res) : resource(res), success(res != nullptr) {} + explicit LoadResult(const Containers::String& error) : success(false), errorMessage(error) {} + explicit LoadResult(bool success, const Containers::String& error = "") + : success(success), errorMessage(error) {} + + operator bool() const { return success && resource != nullptr; } +}; + +class IResourceLoader { +public: + virtual ~IResourceLoader() = default; + + virtual ResourceType GetResourceType() const = 0; + virtual Containers::Array GetSupportedExtensions() const = 0; + virtual bool CanLoad(const Containers::String& path) const = 0; + virtual LoadResult Load(const Containers::String& path, const ImportSettings* settings = nullptr) = 0; + + virtual void LoadAsync(const Containers::String& path, + const ImportSettings* settings, + std::function callback) { + LoadResult result = Load(path, settings); + if (callback) { + callback(result); + } + } + + virtual ImportSettings* GetDefaultSettings() const = 0; + +protected: + static Containers::Array ReadFileData(const Containers::String& path); + static Containers::String GetExtension(const Containers::String& path); +}; + +#define REGISTER_RESOURCE_LOADER(loaderType) \ + namespace { \ + struct loaderType##Registrar { \ + loaderType##Registrar() { \ + ResourceManager::Get().RegisterLoader(new loaderType()); \ + } \ + } g_##loaderType##Registrar; \ + } + +} // namespace Resources +} // namespace XCEngine +``` + +#### 步骤 11.2.6 实现 ResourceManager.h + +**文件**: `engine/include/XCEngine/Resources/ResourceManager.h` + +```cpp +#pragma once +#include "IResourceLoader.h" +#include "ResourceCache.h" +#include "AsyncLoader.h" +#include "../Containers/String.h" +#include "../Containers/Array.h" +#include "../Containers/HashMap.h" +#include "../Threading/Mutex.h" +#include "../Debug/Logger.h" + +namespace XCEngine { +namespace Resources { + +class ResourceManager { +public: + static ResourceManager& Get(); + + void Initialize(); + void Shutdown(); + + void SetResourceRoot(const Containers::String& rootPath); + const Containers::String& GetResourceRoot() const; + + template + ResourceHandle Load(const Containers::String& path, ImportSettings* settings = nullptr) { + static_assert(std::is_base_of_v, "T must derive from IResource"); + + // 实现见文档Section 5.4 + } + + void LoadAsync(const Containers::String& path, ResourceType type, + std::function callback); + void LoadAsync(const Containers::String& path, ResourceType type, ImportSettings* settings, + std::function callback); + + void Unload(const Containers::String& path); + void Unload(ResourceGUID guid); + void UnloadUnused(); + void UnloadAll(); + + void AddRef(ResourceGUID guid); + void Release(ResourceGUID guid); + Core::uint32 GetRefCount(ResourceGUID guid) const; + + void RegisterLoader(IResourceLoader* loader); + void UnregisterLoader(ResourceType type); + IResourceLoader* GetLoader(ResourceType type) const; + + void SetMemoryBudget(size_t bytes); + size_t GetMemoryUsage() const; + size_t GetMemoryBudget() const; + void FlushCache(); + + IResource* Find(const Containers::String& path); + IResource* Find(ResourceGUID guid); + bool Exists(const Containers::String& path) const; + bool Exists(ResourceGUID guid) const; + + Containers::String ResolvePath(const Containers::String& relativePath) const; + +private: + ResourceManager() = default; + ~ResourceManager() = default; + + IResource* FindInCache(ResourceGUID guid); + void AddToCache(ResourceGUID guid, IResource* resource); + IResourceLoader* FindLoader(ResourceType type); + void ReloadResource(ResourceGUID guid); + + Containers::String m_resourceRoot; + Containers::HashMap m_resourceCache; + Containers::HashMap m_refCounts; + Containers::HashMap m_guidToPath; + Containers::HashMap> m_loaders; + + size_t m_memoryUsage = 0; + size_t m_memoryBudget = 512 * 1024 * 1024; + + UniquePtr m_asyncLoader; + Threading::Mutex m_mutex; + + friend class ResourceHandleBase; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +#### 步骤 11.2.7 实现 ResourceManager.cpp + +**文件**: `engine/src/Resources/ResourceManager.cpp` + +```cpp +#include "Resources/ResourceManager.h" +#include "Resources/ResourceHandle.h" + +namespace XCEngine { +namespace Resources { + +ResourceManager& ResourceManager::Get() { + static ResourceManager instance; + return instance; +} + +void ResourceManager::Initialize() { + m_asyncLoader = UniquePtr(new AsyncLoader()); + m_asyncLoader->Initialize(2); // 默认2个工作线程 +} + +void ResourceManager::Shutdown() { + UnloadAll(); + m_asyncLoader->Shutdown(); + m_asyncLoader.Reset(); +} + +void ResourceManager::SetResourceRoot(const Containers::String& rootPath) { + m_resourceRoot = rootPath; +} + +const Containers::String& ResourceManager::GetResourceRoot() const { + return m_resourceRoot; +} + +void ResourceManager::AddRef(ResourceGUID guid) { + std::lock_guard lock(m_mutex); + + auto it = m_refCounts.Find(guid); + if (it == m_refCounts.End()) { + m_refCounts.Insert(guid, 1); + } else { + it->second++; + } + + if (!m_resourceCache.Contains(guid)) { + ReloadResource(guid); + } +} + +void ResourceManager::Release(ResourceGUID guid) { + std::lock_guard lock(m_mutex); + + auto it = m_refCounts.Find(guid); + if (it != m_refCounts.End()) { + it->second--; + + if (it->second == 0) { + m_refCounts.Erase(guid); + m_cache.OnZeroRefCount(guid); + } + } +} + +Core::uint32 ResourceManager::GetRefCount(ResourceGUID guid) const { + std::lock_guard lock(m_mutex); + + auto it = m_refCounts.Find(guid); + return it != m_refCounts.End() ? it->second : 0; +} + +void ResourceManager::RegisterLoader(IResourceLoader* loader) { + std::lock_guard lock(m_mutex); + m_loaders.Insert(loader->GetResourceType(), UniquePtr(loader)); +} + +IResourceLoader* ResourceManager::GetLoader(ResourceType type) const { + std::lock_guard lock(m_mutex); + + auto it = m_loaders.Find(type); + return it != m_loaders.End() ? it->second.Get() : nullptr; +} + +IResourceLoader* ResourceManager::FindLoader(ResourceType type) { + return GetLoader(type); +} + +IResource* ResourceManager::FindInCache(ResourceGUID guid) { + std::lock_guard lock(m_mutex); + + auto it = m_resourceCache.Find(guid); + return it != m_resourceCache.End() ? it->second : nullptr; +} + +void ResourceManager::AddToCache(ResourceGUID guid, IResource* resource) { + std::lock_guard lock(m_mutex); + + m_resourceCache.Insert(guid, resource); + m_memoryUsage += resource->GetMemorySize(); + m_cache.Add(guid, resource); + + if (m_memoryUsage > m_memoryBudget) { + m_cache.OnMemoryPressure(m_memoryUsage - m_memoryBudget); + } +} + +void ResourceManager::Unload(ResourceGUID guid) { + std::lock_guard lock(m_mutex); + + auto it = m_resourceCache.Find(guid); + if (it != m_resourceCache.End()) { + IResource* resource = it->second; + m_resourceCache.Erase(guid); + m_memoryUsage -= resource->GetMemorySize(); + resource->Release(); + } +} + +void ResourceManager::UnloadAll() { + std::lock_guard lock(m_mutex); + + for (auto& pair : m_resourceCache) { + pair.second->Release(); + } + m_resourceCache.Clear(); + m_refCounts.Clear(); + m_memoryUsage = 0; +} + +void ResourceManager::SetMemoryBudget(size_t bytes) { + m_memoryBudget = bytes; +} + +size_t ResourceManager::GetMemoryUsage() const { + return m_memoryUsage; +} + +size_t ResourceManager::GetMemoryBudget() const { + return m_memoryBudget; +} + +void ResourceManager::FlushCache() { + m_cache.Flush(); +} + +IResource* ResourceManager::Find(const Containers::String& path) { + ResourceGUID guid = MakeResourceGUID(path.CStr()); + return Find(guid); +} + +IResource* ResourceManager::Find(ResourceGUID guid) { + return FindInCache(guid); +} + +bool ResourceManager::Exists(const Containers::String& path) const { + return Find(MakeResourceGUID(path.CStr())) != nullptr; +} + +bool ResourceManager::Exists(ResourceGUID guid) const { + return false; // 需要实现 +} + +Containers::String ResourceManager::ResolvePath(const Containers::String& relativePath) const { + return m_resourceRoot + "/" + relativePath; +} + +void ResourceManager::LoadAsync(const Containers::String& path, ResourceType type, + std::function callback) { + LoadAsync(path, type, nullptr, callback); +} + +void ResourceManager::LoadAsync(const Containers::String& path, ResourceType type, + ImportSettings* settings, + std::function)> callback) { + m_asyncLoader->Submit(path, type, settings, callback); +} + +void ResourceManager::Unload(const Containers::String& path) { + Unload(MakeResourceGUID(path.CStr())); +} + +void ResourceManager::UnloadUnused() { + // 实现清理未使用资源 +} + +void ResourceManager::UnregisterLoader(ResourceType type) { + m_loaders.Erase(type); +} + +void ResourceManager::ReloadResource(ResourceGUID guid) { + // 实现重新加载逻辑 +} + +} // namespace Resources +} // namespace XCEngine +``` + +### 11.3 第二阶段:缓存系统(天4-5) + +#### 步骤 11.3.1 实现 ResourceCache.h + +**文件**: `engine/include/XCEngine/Resources/ResourceCache.h` + +```cpp +#pragma once +#include "ResourceTypes.h" +#include "../Containers/HashMap.h" +#include "../Containers/Array.h" +#include "../Threading/Mutex.h" +#include + +namespace XCEngine { +namespace Resources { + +struct CacheEntry { + IResource* resource; + ResourceGUID guid; + size_t memorySize; + Core::uint64 lastAccessTime; + Core::uint32 accessCount; + + CacheEntry() : resource(nullptr), memorySize(0), lastAccessTime(0), accessCount(0) {} + CacheEntry(IResource* res, size_t size) + : resource(res), guid(res->GetGUID()), memorySize(size), + lastAccessTime(GetCurrentTick()), accessCount(1) {} + +private: + static Core::uint64 GetCurrentTick(); +}; + +class ResourceCache { +public: + ResourceCache(); + ~ResourceCache(); + + void Add(ResourceGUID guid, IResource* resource); + void Remove(ResourceGUID guid); + IResource* Find(ResourceGUID guid) const; + void Touch(ResourceGUID guid); + + size_t GetSize() const { return m_cache.Size(); } + size_t GetMemoryUsage() const { return m_memoryUsage; } + + void SetMemoryBudget(size_t bytes); + size_t GetMemoryBudget() const { return m_memoryBudget; } + + void OnMemoryPressure(size_t requiredBytes); + void OnZeroRefCount(ResourceGUID guid); + void Flush(); + void Clear(); + + Containers::Array GetLRUList(size_t count) const; + +private: + void Evict(size_t requiredBytes); + void UpdateMemoryStats(); + + Containers::HashMap m_cache; + Containers::Array m_lruOrder; + size_t m_memoryUsage = 0; + size_t m_memoryBudget = 512 * 1024 * 1024; + + Threading::Mutex m_mutex; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +#### 步骤 11.3.2 实现 ResourceCache.cpp + +**文件**: `engine/src/Resources/ResourceCache.cpp` + +```cpp +#include "Resources/ResourceCache.h" + +namespace XCEngine { +namespace Resources { + +// 简单的时间戳实现,实际可使用Profiler::Get().GetTickCount() +static Core::uint64 g_currentTick = 0; +Core::uint64 CacheEntry::GetCurrentTick() { + return ++g_currentTick; +} + +ResourceCache::ResourceCache() = default; +ResourceCache::~ResourceCache() = default; + +void ResourceCache::Add(ResourceGUID guid, IResource* resource) { + std::lock_guard lock(m_mutex); + + if (m_cache.Contains(guid)) { + return; // 已存在 + } + + CacheEntry entry(resource, resource->GetMemorySize()); + m_cache.Insert(guid, entry); + m_lruOrder.Add(guid); + m_memoryUsage += entry.memorySize; +} + +void ResourceCache::Remove(ResourceGUID guid) { + std::lock_guard lock(m_mutex); + + auto it = m_cache.Find(guid); + if (it != m_cache.End()) { + m_memoryUsage -= it->second.memorySize; + m_cache.Erase(guid); + + for (auto lit = m_lruOrder.Begin(); lit != m_lruOrder.End(); ++lit) { + if (*lit == guid) { + m_lruOrder.Erase(lit); + break; + } + } + } +} + +IResource* ResourceCache::Find(ResourceGUID guid) const { + std::lock_guard lock(m_mutex); + + auto it = m_cache.Find(guid); + return it != m_cache.End() ? it->second.resource : nullptr; +} + +void ResourceCache::Touch(ResourceGUID guid) { + std::lock_guard lock(m_mutex); + + auto it = m_cache.Find(guid); + if (it != m_cache.End()) { + it->second.lastAccessTime = CacheEntry::GetCurrentTick(); + it->second.accessCount++; + } +} + +void ResourceCache::SetMemoryBudget(size_t bytes) { + std::lock_guard lock(m_mutex); + m_memoryBudget = bytes; +} + +void ResourceCache::OnMemoryPressure(size_t requiredBytes) { + std::lock_guard lock(m_mutex); + + if (m_memoryUsage + requiredBytes <= m_memoryBudget) { + return; + } + + size_t targetRelease = (m_memoryUsage + requiredBytes) - m_memoryBudget; + Evict(targetRelease); +} + +void ResourceCache::OnZeroRefCount(ResourceGUID guid) { + // 引用计数为0时,标记资源可以被淘汰 + // 实际淘汰由LRU策略决定 +} + +void ResourceCache::Evict(size_t requiredBytes) { + size_t released = 0; + + for (auto it = m_lruOrder.Begin(); it != m_lruOrder.End() && released < requiredBytes; ) { + ResourceGUID guid = *it; + auto cacheIt = m_cache.Find(guid); + + if (cacheIt != m_cache.End()) { + CacheEntry& entry = cacheIt->second; + + if (ResourceManager::Get().GetRefCount(guid) == 0) { + size_t entrySize = entry.memorySize; + + m_cache.Erase(guid); + m_memoryUsage -= entrySize; + released += entrySize; + + entry.resource->Release(); + it = m_lruOrder.Erase(it); + } else { + ++it; + } + } else { + ++it; + } + } +} + +void ResourceCache::Flush() { + std::lock_guard lock(m_mutex); + + for (auto& pair : m_cache) { + if (ResourceManager::Get().GetRefCount(pair.first) == 0) { + pair.second.resource->Release(); + } + } + + m_cache.Clear(); + m_lruOrder.Clear(); + m_memoryUsage = 0; +} + +void ResourceCache::Clear() { + std::lock_guard lock(m_mutex); + m_cache.Clear(); + m_lruOrder.Clear(); + m_memoryUsage = 0; +} + +Containers::Array ResourceCache::GetLRUList(size_t count) const { + std::lock_guard lock(m_mutex); + + Containers::Array result; + size_t n = std::min(count, static_cast(m_lruOrder.Size())); + + for (size_t i = 0; i < n; i++) { + result.Add(m_lruOrder[i]); + } + + return result; +} + +} // namespace Resources +} // namespace XCEngine +``` + +### 11.4 第三阶段:异步加载(天6-7) + +#### 步骤 11.4.1 实现 AsyncLoader.h + +**文件**: `engine/include/XCEngine/Resources/AsyncLoader.h` + +```cpp +#pragma once +#include "IResourceLoader.h" +#include "../Containers/Array.h" +#include "../Threading/Mutex.h" +#include +#include + +namespace XCEngine { +namespace Resources { + +struct LoadRequest { + Containers::String path; + ResourceType type; + std::function callback; + UniquePtr settings; + Core::uint64 requestId; + + LoadRequest() : requestId(0) {} + + LoadRequest(const Containers::String& p, ResourceType t, + std::function cb, ImportSettings* s = nullptr) + : path(p), type(t), callback(std::move(cb)), + settings(s), requestId(GenerateRequestId()) {} + +private: + static Core::uint64 GenerateRequestId(); +}; + +class LoadTask : public Threading::ITask { +public: + LoadTask(LoadRequest request, IResourceLoader* loader); + + void Execute() override; + LoadResult& GetResult() { return m_result; } + +private: + LoadRequest m_request; + IResourceLoader* m_loader; + LoadResult m_result; +}; + +class AsyncLoader { +public: + static AsyncLoader& Get(); + + void Initialize(Core::uint32 workerThreadCount = 2); + void Shutdown(); + + void Submit(const Containers::String& path, ResourceType type, + std::function callback); + void Submit(const Containers::String& path, ResourceType type, ImportSettings* settings, + std::function callback); + + void Update(); + bool IsLoading() const { return m_pendingCount > 0; } + Core::uint32 GetPendingCount() const { return m_pendingCount; } + float GetProgress() const; + void CancelAll(); + void Cancel(Core::uint64 requestId); + +private: + AsyncLoader() = default; + ~AsyncLoader() = default; + + void SubmitInternal(LoadRequest& request); + IResourceLoader* FindLoader(ResourceType type) const; + + Threading::Mutex m_queueMutex; + Containers::Array m_pendingQueue; + + Threading::Mutex m_completedMutex; + Containers::Array m_completedQueue; + + std::atomic m_pendingCount{0}; + std::atomic m_completedCount{0}; + Core::uint32 m_totalRequested = 0; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +#### 步骤 11.4.2 实现 AsyncLoader.cpp + +**文件**: `engine/src/Resources/AsyncLoader.cpp` + +```cpp +#include "Resources/AsyncLoader.h" +#include "Resources/ResourceManager.h" +#include "../Threading/TaskSystem.h" + +namespace XCEngine { +namespace Resources { + +Core::uint64 LoadRequest::GenerateRequestId() { + static std::atomic s_requestId{0}; + return ++s_requestId; +} + +LoadTask::LoadTask(LoadRequest request, IResourceLoader* loader) + : m_request(std::move(request)), m_loader(loader) {} + +void LoadTask::Execute() { + m_result = m_loader->Load(m_request.path, m_request.settings.Get()); + + // 放入完成队列 + AsyncLoader::Get().QueueCompleted(std::move(m_request), std::move(m_result)); +} + +AsyncLoader& AsyncLoader::Get() { + static AsyncLoader instance; + return instance; +} + +void AsyncLoader::Initialize(Core::uint32 workerThreadCount) { + // TaskSystem已初始化,此处不需要额外操作 +} + +void AsyncLoader::Shutdown() { + CancelAll(); +} + +void AsyncLoader::Submit(const Containers::String& path, ResourceType type, + std::function callback) { + Submit(path, type, nullptr, callback); +} + +void AsyncLoader::Submit(const Containers::String& path, ResourceType type, + ImportSettings* settings, std::function callback) { + LoadRequest request(path, type, callback, settings); + SubmitInternal(request); +} + +void AsyncLoader::SubmitInternal(LoadRequest& request) { + IResourceLoader* loader = FindLoader(request.type); + if (!loader) { + if (request.callback) { + LoadResult result(Containers::String("No loader for type: ") + + GetResourceTypeName(request.type)); + request.callback(result); + } + return; + } + + { + std::lock_guard lock(m_queueMutex); + m_pendingQueue.Add(request); + m_pendingCount++; + m_totalRequested++; + } + + // 提交到任务系统 + auto task = new LoadTask(request, loader); + Threading::TaskSystem::Get().Submit(UniquePtr(task)); +} + +void AsyncLoader::Update() { + Containers::Array completed; + + { + std::lock_guard lock(m_completedMutex); + completed = std::move(m_completedQueue); + m_completedQueue.Clear(); + } + + for (auto& request : completed) { + m_pendingCount--; + + if (request.callback) { + request.callback(m_completedResults[request.requestId]); + } + } + + m_completedResults.Clear(); +} + +float AsyncLoader::GetProgress() const { + if (m_totalRequested == 0) return 1.0f; + return static_cast(m_totalRequested - m_pendingCount) / m_totalRequested; +} + +void AsyncLoader::CancelAll() { + std::lock_guard lock(m_queueMutex); + m_pendingQueue.Clear(); + m_pendingCount = 0; +} + +void AsyncLoader::Cancel(Core::uint64 requestId) { + std::lock_guard lock(m_queueMutex); + + for (auto it = m_pendingQueue.Begin(); it != m_pendingQueue.End(); ++it) { + if (it->requestId == requestId) { + m_pendingQueue.Erase(it); + m_pendingCount--; + return; + } + } +} + +IResourceLoader* AsyncLoader::FindLoader(ResourceType type) const { + return ResourceManager::Get().GetLoader(type); +} + +} // namespace Resources +} // namespace XCEngine +``` + +### 11.5 第四阶段:具体资源类型(天8-11) + +#### 步骤 11.5.1 实现 Texture 及其加载器 + +**文件**: `engine/include/XCEngine/Resources/Texture.h` + +```cpp +#pragma once +#include "IResource.h" +#include "../Core/Types.h" + +namespace XCEngine { +namespace Resources { + +enum class TextureType { + Texture2D, Texture3D, TextureCube, Texture2DArray, TextureCubeArray +}; + +enum class TextureFormat { + Unknown, R8_UNORM, RG8_UNORM, RGBA8_UNORM, RGBA8_SRGB, + R16_FLOAT, RG16_FLOAT, RGBA16_FLOAT, + R32_FLOAT, RG32_FLOAT, RGBA32_FLOAT, + D16_UNORM, D24_UNORM_S8_UINT, D32_FLOAT, D32_FLOAT_S8_X24_UINT, + BC1_UNORM, BC1_UNORM_SRGB, BC2_UNORM, BC2_UNORM_SRGB, + BC3_UNORM, BC3_UNORM_SRGB, BC4_UNORM, BC5_UNORM, BC6H_UF16, + BC7_UNORM, BC7_UNORM_SRGB +}; + +enum class TextureUsage : Core::uint8 { + None = 0, ShaderResource = 1 << 0, RenderTarget = 1 << 1, + DepthStencil = 1 << 2, UnorderedAccess = 1 << 3, + TransferSrc = 1 << 4, TransferDst = 1 << 5 +}; + +class Texture : public IResource { +public: + Texture(); + virtual ~Texture() override; + + ResourceType GetType() const override { return ResourceType::Texture; } + const Containers::String& GetName() const override { return m_name; } + const Containers::String& GetPath() const override { return m_path; } + ResourceGUID GetGUID() const override { return m_guid; } + bool IsValid() const override { return m_isValid; } + size_t GetMemorySize() const override { return m_memorySize; } + void Release() override; + + Core::uint32 GetWidth() const { return m_width; } + Core::uint32 GetHeight() const { return m_height; } + Core::uint32 GetDepth() const { return m_depth; } + Core::uint32 GetMipLevels() const { return m_mipLevels; } + Core::uint32 GetArraySize() const { return m_arraySize; } + TextureType GetTextureType() const { return m_textureType; } + TextureFormat GetFormat() const { return m_format; } + TextureUsage GetUsage() const { return m_usage; } + + class IRHIResource* GetRHIResource() const { return m_rhiResource; } + void SetRHIResource(class IRHIResource* resource); + + bool Create(Core::uint32 width, Core::uint32 height, Core::uint32 depth, + Core::uint32 mipLevels, TextureType type, TextureFormat format, + const void* data, size_t dataSize); + bool GenerateMipmaps(); + +private: + Core::uint32 m_width = 0; + Core::uint32 m_height = 0; + Core::uint32 m_depth = 1; + Core::uint32 m_mipLevels = 1; + Core::uint32 m_arraySize = 1; + TextureType m_textureType = TextureType::Texture2D; + TextureFormat m_format = TextureFormat::RGBA8_UNORM; + TextureUsage m_usage = TextureUsage::ShaderResource; + + class IRHIResource* m_rhiResource = nullptr; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +**实现要点**: +1. 使用stb_image库加载PNG/JPG/TGA +2. 支持生成Mipmap +3. 完成后创建RHI资源 + +#### 步骤 11.5.2 实现 Mesh 及其加载器 + +**文件**: `engine/include/XCEngine/Resources/Mesh.h` + +```cpp +#pragma once +#include "IResource.h" +#include "../Containers/Array.h" +#include "../Math/AABB.h" + +namespace XCEngine { +namespace Resources { + +enum class VertexAttribute : Core::uint32 { + Position = 1 << 0, Normal = 1 << 1, Tangent = 1 << 2, + Color = 1 << 3, UV0 = 1 << 4, UV1 = 1 << 5, + UV2 = 1 << 6, UV3 = 1 << 7, BoneWeights = 1 << 8, BoneIndices = 1 << 9 +}; + +struct MeshSection { + Core::uint32 baseVertex; + Core::uint32 vertexCount; + Core::uint32 startIndex; + Core::uint32 indexCount; + Core::uint32 materialID; + Math::AABB boundingBox; +}; + +class Mesh : public IResource { +public: + Mesh(); + virtual ~Mesh() override; + + ResourceType GetType() const override { return ResourceType::Mesh; } + const Containers::String& GetName() const override { return m_name; } + const Containers::String& GetPath() const override { return m_path; } + ResourceGUID GetGUID() const override { return m_guid; } + bool IsValid() const override { return m_isValid; } + size_t GetMemorySize() const override { return m_memorySize; } + void Release() override; + + void SetVertexData(const void* data, size_t size, Core::uint32 vertexCount, + Core::uint32 vertexStride, VertexAttribute attributes); + const void* GetVertexData() const { return m_vertexData.Data(); } + size_t GetVertexDataSize() const { return m_vertexData.Size(); } + Core::uint32 GetVertexCount() const { return m_vertexCount; } + Core::uint32 GetVertexStride() const { return m_vertexStride; } + VertexAttribute GetVertexAttributes() const { return m_attributes; } + + void SetIndexData(const void* data, size_t size, Core::uint32 indexCount, bool use32Bit); + const void* GetIndexData() const { return m_indexData.Data(); } + size_t GetIndexDataSize() const { return m_indexData.Size(); } + Core::uint32 GetIndexCount() const { return m_indexCount; } + bool IsUse32BitIndex() const { return m_use32BitIndex; } + + void AddSection(const MeshSection& section); + const Containers::Array& GetSections() const { return m_sections; } + + void SetBoundingBox(const Math::AABB& box); + const Math::AABB& GetBoundingBox() const { return m_boundingBox; } + + class IRHIBuffer* GetVertexBuffer() const { return m_vertexBuffer; } + class IRHIBuffer* GetIndexBuffer() const { return m_indexBuffer; } + void SetRHIBuffers(class IRHIBuffer* vb, class IRHIBuffer* ib); + +private: + Containers::Array m_vertexData; + Core::uint32 m_vertexCount = 0; + Core::uint32 m_vertexStride = 0; + VertexAttribute m_attributes = VertexAttribute::Position; + + Containers::Array m_indexData; + Core::uint32 m_indexCount = 0; + bool m_use32BitIndex = false; + + Containers::Array m_sections; + Math::AABB m_boundingBox; + + class IRHIBuffer* m_vertexBuffer = nullptr; + class IRHIBuffer* m_indexBuffer = nullptr; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +#### 步骤 11.5.3 实现 Material 及其加载器 + +**文件**: `engine/include/XCEngine/Resources/Material.h` + +```cpp +#pragma once +#include "IResource.h" +#include "ResourceHandle.h" +#include "Texture.h" +#include "../Containers/HashMap.h" +#include "../Math/Vector2.h" +#include "../Math/Vector3.h" +#include "../Math/Vector4.h" + +namespace XCEngine { +namespace Resources { + +enum class MaterialPropertyType { + Float, Float2, Float3, Float4, + Int, Int2, Int3, Int4, + Bool, Texture, Cubemap +}; + +struct MaterialProperty { + Containers::String name; + MaterialPropertyType type; + + union Value { + float floatValue[4]; + Core::int32 intValue[4]; + bool boolValue; + ResourceHandle textureValue; + + Value() { memset(this, 0, sizeof(Value)); } + } value; + + Core::uint32 refCount; +}; + +class Material : public IResource { +public: + Material(); + virtual ~Material() override; + + ResourceType GetType() const override { return ResourceType::Material; } + const Containers::String& GetName() const override { return m_name; } + const Containers::String& GetPath() const override { return m_path; } + ResourceGUID GetGUID() const override { return m_guid; } + bool IsValid() const override { return m_isValid; } + size_t GetMemorySize() const override { return m_memorySize; } + void Release() override; + + void SetShader(const ResourceHandle& shader); + class Shader* GetShader() const { return m_shader.Get(); } + + void SetFloat(const Containers::String& name, float value); + void SetFloat2(const Containers::String& name, const Math::Vector2& value); + void SetFloat3(const Containers::String& name, const Math::Vector3& value); + void SetFloat4(const Containers::String& name, const Math::Vector4& value); + void SetInt(const Containers::String& name, int32 value); + void SetBool(const Containers::String& name, bool value); + void SetTexture(const Containers::String& name, const ResourceHandle& texture); + + float GetFloat(const Containers::String& name) const; + ResourceHandle GetTexture(const Containers::String& name) const; + + const Containers::Array& GetConstantBufferData() const { return m_constantBufferData; } + void UpdateConstantBuffer(); + +private: + ResourceHandle m_shader; + Containers::HashMap m_properties; + Containers::Array m_constantBufferData; + + struct TextureBinding { + Containers::String name; + Core::uint32 slot; + ResourceHandle texture; + }; + Containers::Array m_textureBindings; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +#### 步骤 11.5.4 实现 AudioClip 及其加载器 + +类似实现,支持WAV格式加载。 + +### 11.6 第五阶段:文件系统集成(天12-13) + +#### 步骤 11.6.1 实现 ResourceFileSystem + +**文件**: `engine/include/XCEngine/Resources/ResourceFileSystem.h` + +```cpp +#pragma once +#include "ResourceTypes.h" +#include "../Containers/String.h" +#include "../Containers/Array.h" +#include "../Containers/HashMap.h" + +namespace XCEngine { +namespace Resources { + +class ResourceFileSystem { +public: + ResourceFileSystem(); + ~ResourceFileSystem(); + + void Initialize(const Containers::String& rootPath); + void Shutdown(); + + bool AddArchive(const Containers::String& archivePath); + bool AddDirectory(const Containers::String& directoryPath); + void RemoveArchive(const Containers::String& archivePath); + + bool FindResource(const Containers::String& relativePath, + Containers::String& outAbsolutePath) const; + Containers::Array ReadResource(const Containers::String& relativePath) const; + bool Exists(const Containers::String& relativePath) const; + + struct ResourceInfo { + Containers::String path; + size_t size; + Core::uint64 modifiedTime; + bool inArchive; + Containers::String archivePath; + }; + + bool GetResourceInfo(const Containers::String& relativePath, ResourceInfo& outInfo) const; + void EnumerateResources(const Containers::String& pattern, + Containers::Array& outResources) const; + +private: + class IArchive { + public: + virtual ~IArchive() = default; + virtual bool Open(const Containers::String& path) = 0; + virtual void Close() = 0; + virtual bool Read(const Containers::String& fileName, void* buffer, + size_t size, size_t offset) const = 0; + virtual size_t GetSize(const Containers::String& fileName) const = 0; + virtual bool Exists(const Containers::String& fileName) const = 0; + virtual void Enumerate(const Containers::String& pattern, + Containers::Array& outFiles) const = 0; + }; + + Containers::String m_rootPath; + Containers::Array> m_archives; + Containers::Array m_directories; + mutable Containers::HashMap m_infoCache; +}; + +} // namespace Resources +} // namespace XCEngine +``` + +### 11.7 第六阶段:依赖管理(天14-15) + +#### 步骤 11.7.1 实现 ResourceDependencyGraph + +```cpp +// 见文档Section 9 +``` + +### 11.8 第七阶段:测试与集成(天16-17) + +#### 步骤 11.8.1 单元测试 + +创建测试用例: +1. 资源加载/卸载 +2. 引用计数 +3. 缓存淘汰 +4. 异步加载 +5. 多线程安全 + +#### 步骤 11.8.2 集成到现有mvs项目 + +在示例应用中使用资源系统加载纹理和模型。 + +### 11.9 每日任务清单 + +| 天数 | 任务 | 完成标准 | +|------|------|----------| +| 1 | 创建目录结构 + Resources.h + ResourceTypes.h | 编译通过 | +| 2 | IResource.h + ResourceHandle.h | 智能指针正常工作 | +| 3 | IResourceLoader.h + ResourceManager.h框架 | 加载器接口完成 | +| 4 | ResourceCache.h/cpp | LRU淘汰正常 | +| 5 | ResourceManager与Cache集成 | 引用计数正常 | +| 6 | AsyncLoader.h/cpp框架 | 任务提交正常 | +| 7 | 异步回调机制 | 主线程回调正常 | +| 8 | Texture.h + 基础加载 | PNG加载成功 | +| 9 | Texture RHI资源创建 | 渲染器能使用 | +| 10 | Mesh.h + 加载器 | OBJ加载成功 | +| 11 | Material.h + 加载器 | JSON材质加载 | +| 12 | ResourceFileSystem | 目录/归档支持 | +| 13 | 资源打包Builder | 打包成功 | +| 14 | DependencyGraph | 依赖关系正确 | +| 15 | 资源组加载 | 批量加载正常 | +| 16 | 单元测试 | 测试通过 | +| 17 | 集成测试 | 示例运行正常 | + +--- + +## 12. 测试设计 + +> 本节详细说明资源系统的测试设计,确保每个阶段完成后都能立即进行测试验收。测试采用Google Test框架,与现有项目保持一致。 + +### 12.1 测试目录结构 + +``` +tests/ +├── Resources/ # 新增资源系统测试 +│ ├── CMakeLists.txt # 构建配置 +│ ├── fixtures/ +│ │ └── ResourcesTestFixture.h # 测试夹具基类 +│ ├── test_resource_types.cpp # 资源类型测试 +│ ├── test_resource_guid.cpp # GUID生成测试 +│ ├── test_iresource.cpp # 资源接口测试 +│ ├── test_resource_handle.cpp # 资源句柄测试 +│ ├── test_resource_cache.cpp # 缓存测试 +│ ├── test_async_loader.cpp # 异步加载测试 +│ ├── test_texture.cpp # 纹理资源测试 +│ ├── test_mesh.cpp # 网格资源测试 +│ ├── test_material.cpp # 材质资源测试 +│ ├── test_audio_clip.cpp # 音频资源测试 +│ ├── test_resource_manager.cpp # 资源管理器测试 +│ ├── test_resource_filesystem.cpp # 文件系统测试 +│ ├── test_resource_dependency.cpp # 依赖管理测试 +│ └── test_data/ +│ ├── test_texture.png # 测试用纹理 +│ ├── test_mesh.obj # 测试用模型 +│ └── test_material.json # 测试用材质 +``` + +### 12.2 测试夹具基类 + +**文件**: `tests/Resources/fixtures/ResourcesTestFixture.h` + +```cpp +#pragma once + +#include +#include +#include +#include + +namespace XCEngine { +namespace Resources { +namespace Test { + +class ResourcesTestFixture : public ::testing::Test { +protected: + static void SetUpTestSuite() { + // 初始化资源系统 + ResourceManager::Get().Initialize(); + ResourceManager::Get().SetResourceRoot("tests/Resources/test_data/"); + AsyncLoader::Get().Initialize(2); + } + + static void TearDownTestSuite() { + ResourceManager::Get().UnloadAll(); + AsyncLoader::Get().Shutdown(); + ResourceManager::Get().Shutdown(); + } + + void SetUp() override { + // 每个测试前清空缓存 + ResourceManager::Get().UnloadAll(); + ResourceManager::Get().FlushCache(); + } + + void TearDown() override { + // 每个测试后确保清空资源 + ResourceManager::Get().UnloadAll(); + } + + // 辅助方法:获取测试数据目录 + Containers::String GetTestDataPath(const Containers::String& filename) { + return Containers::String("tests/Resources/test_data/") + filename; + } +}; + +} // namespace Test +} // namespace Resources +} // namespace XCEngine +``` + +### 12.3 第一阶段测试:基础框架(天1-3完成后) + +#### 测试 12.3.1 资源类型枚举测试 + +**文件**: `tests/Resources/test_resource_types.cpp` + +```cpp +#include +#include + +using namespace XCEngine::Resources; + +namespace { + +TEST(Resources_Types, ResourceType_EnumValues) { + EXPECT_EQ(static_cast(ResourceType::Unknown), 0); + EXPECT_EQ(static_cast(ResourceType::Texture), 1); + EXPECT_EQ(static_cast(ResourceType::Mesh), 2); + EXPECT_EQ(static_cast(ResourceType::Material), 3); + EXPECT_EQ(static_cast(ResourceType::Shader), 4); + EXPECT_EQ(static_cast(ResourceType::AudioClip), 5); + EXPECT_EQ(static_cast(ResourceType::Binary), 6); +} + +TEST(Resources_Types, GetResourceTypeName) { + EXPECT_STREQ(GetResourceTypeName(ResourceType::Texture), "Texture"); + EXPECT_STREQ(GetResourceTypeName(ResourceType::Mesh), "Mesh"); + EXPECT_STREQ(GetResourceTypeName(ResourceType::Material), "Material"); + EXPECT_STREQ(GetResourceTypeName(ResourceType::Unknown), "Unknown"); +} + +TEST(Resources_Types, GetResourceType_TemplateSpecializations) { + EXPECT_EQ(GetResourceType(), ResourceType::Texture); + EXPECT_EQ(GetResourceType(), ResourceType::Mesh); + EXPECT_EQ(GetResourceType(), ResourceType::Material); + EXPECT_EQ(GetResourceType(), ResourceType::Shader); + EXPECT_EQ(GetResourceType(), ResourceType::AudioClip); + EXPECT_EQ(GetResourceType(), ResourceType::Binary); +} + +} // namespace +``` + +#### 测试 12.3.2 ResourceGUID测试 + +**文件**: `tests/Resources/test_resource_guid.cpp` + +```cpp +#include +#include + +using namespace XCEngine::Resources; + +namespace { + +TEST(Resources_GUID, DefaultConstructor) { + ResourceGUID guid; + EXPECT_FALSE(guid.IsValid()); + EXPECT_EQ(guid.value, 0); +} + +TEST(Resources_GUID, ValueConstructor) { + ResourceGUID guid(12345); + EXPECT_TRUE(guid.IsValid()); + EXPECT_EQ(guid.value, 12345); +} + +TEST(Resources_GUID, Generate_FromCString) { + ResourceGUID guid1 = ResourceGUID::Generate("textures/player.png"); + ResourceGUID guid2 = ResourceGUID::Generate("textures/player.png"); + + // 相同路径应生成相同GUID + EXPECT_EQ(guid1, guid2); + EXPECT_TRUE(guid1.IsValid()); +} + +TEST(Resources_GUID, Generate_FromString) { + Containers::String path = "models/player.fbx"; + ResourceGUID guid = ResourceGUID::Generate(path); + EXPECT_TRUE(guid.IsValid()); +} + +TEST(Resources_GUID, Generate_DifferentPaths) { + ResourceGUID guid1 = ResourceGUID::Generate("textures/a.png"); + ResourceGUID guid2 = ResourceGUID::Generate("textures/b.png"); + + // 不同路径应生成不同GUID + EXPECT_NE(guid1, guid2); +} + +TEST(Resources_GUID, ToString) { + ResourceGUID guid(0x1234567890ABCDEF); + Containers::String str = guid.ToString(); + + EXPECT_EQ(str.Size(), 16u); + EXPECT_STREQ(str.CStr(), "1234567890abcdef"); +} + +TEST(Resources_GUID, MakeResourceGUID_Helper) { + ResourceGUID guid = MakeResourceGUID("test/path"); + EXPECT_TRUE(guid.IsValid()); +} + +TEST(Resources_GUID, EqualityOperators) { + ResourceGUID guid1(100); + ResourceGUID guid2(100); + ResourceGUID guid3(200); + + EXPECT_TRUE(guid1 == guid2); + EXPECT_TRUE(guid1 != guid3); +} + +} // namespace +``` + +#### 测试 12.3.3 资源句柄测试 + +**文件**: `tests/Resources/test_resource_handle.cpp` + +```cpp +#include +#include +#include + +using namespace XCEngine::Resources; + +// 测试用伪资源 +class TestResource : public IResource { +public: + TestResource(const Containers::String& name) { + ConstructParams params; + params.name = name; + params.path = name; + params.guid = ResourceGUID::Generate(name.CStr()); + params.memorySize = 1024; + Initialize(params); + } + + ResourceType GetType() const override { return ResourceType::Binary; } + const Containers::String& GetName() const override { return m_name; } + const Containers::String& GetPath() const override { return m_path; } + ResourceGUID GetGUID() const override { return m_guid; } + bool IsValid() const override { return m_isValid; } + size_t GetMemorySize() const override { return m_memorySize; } + void Release() override { delete this; } +}; + +namespace { + +TEST(Resources_Handle, DefaultConstructor) { + ResourceHandle handle; + EXPECT_FALSE(handle.IsValid()); + EXPECT_EQ(handle.Get(), nullptr); +} + +TEST(Resources_Handle, ConstructorWithValidResource) { + TestResource* resource = new TestResource("test_resource"); + ResourceHandle handle(resource); + + EXPECT_TRUE(handle.IsValid()); + EXPECT_EQ(handle.Get(), resource); + EXPECT_EQ(handle->GetName().CStr(), Containers::String("test_resource")); +} + +TEST(Resources_Handle, CopyConstructor_AddsRef) { + TestResource* resource = new TestResource("test_resource"); + ResourceHandle handle1(resource); + + Core::uint32 refCountBefore = ResourceManager::Get().GetRefCount(resource->GetGUID()); + + ResourceHandle handle2(handle1); + + Core::uint32 refCountAfter = ResourceManager::Get().GetRefCount(resource->GetGUID()); + EXPECT_EQ(refCountAfter, refCountBefore + 1); +} + +TEST(Resources_Handle, MoveConstructor_DoesNotAddRef) { + TestResource* resource = new TestResource("test_resource"); + ResourceHandle handle1(resource); + + Core::uint32 refCountBefore = ResourceManager::Get().GetRefCount(resource->GetGUID()); + + ResourceHandle handle2(std::move(handle1)); + + // 移动语义不应增加引用计数 + EXPECT_EQ(handle1.Get(), nullptr); + EXPECT_EQ(handle2.Get(), resource); +} + +TEST(Resources_Handle, Destructor_ReleasesRef) { + TestResource* resource = new TestResource("test_resource"); + { + ResourceHandle handle(resource); + EXPECT_TRUE(handle.IsValid()); + } + // handle销毁后应释放引用 + // 注意:此时资源应该被卸载(因为引用计数为0) +} + +TEST(Resources_Handle, Reset) { + TestResource* resource = new TestResource("test_resource"); + ResourceHandle handle(resource); + + EXPECT_TRUE(handle.IsValid()); + handle.Reset(); + + EXPECT_FALSE(handle.IsValid()); + EXPECT_EQ(handle.Get(), nullptr); +} + +TEST(Resources_Handle, ArrowOperator) { + TestResource* resource = new TestResource("test_resource"); + ResourceHandle handle(resource); + + EXPECT_STREQ(handle->GetName().CStr(), "test_resource"); + EXPECT_EQ(handle->GetGUID(), resource->GetGUID()); +} + +TEST(Resources_Handle, BoolOperator) { + ResourceHandle emptyHandle; + TestResource* resource = new TestResource("test"); + ResourceHandle validHandle(resource); + + EXPECT_FALSE(emptyHandle); + EXPECT_TRUE(validHandle); +} + +TEST(Resources_Handle, GetGUID) { + TestResource* resource = new TestResource("test_resource"); + ResourceHandle handle(resource); + + EXPECT_EQ(handle.GetGUID(), resource->GetGUID()); + EXPECT_TRUE(handle.GetGUID().IsValid()); +} + +TEST(Resources_Handle, GetResourceType) { + TestResource* resource = new TestResource("test_resource"); + ResourceHandle handle(resource); + + EXPECT_EQ(handle.GetResourceType(), ResourceType::Binary); +} + +TEST(Resources_Handle, EqualityOperators) { + TestResource* resource = new TestResource("test"); + ResourceHandle handle1(resource); + ResourceHandle handle2(resource); + + EXPECT_TRUE(handle1 == handle2); + + TestResource* resource2 = new TestResource("test2"); + ResourceHandle handle3(resource2); + + EXPECT_TRUE(handle1 != handle3); +} + +} // namespace +``` + +### 12.4 第二阶段测试:缓存系统(天4-5完成后) + +#### 测试 12.4.1 资源缓存测试 + +**文件**: `tests/Resources/test_resource_cache.cpp` + +```cpp +#include +#include +#include "fixtures/ResourcesTestFixture.h" + +using namespace XCEngine::Resources; + +namespace { + +class ResourceCache_Test : public ResourcesTestFixture { +protected: + void SetUp() override { + ResourcesTestFixture::SetUp(); + m_cache = new ResourceCache(); + } + + void TearDown() override { + delete m_cache; + ResourcesTestFixture::TearDown(); + } + + ResourceCache* m_cache; +}; + +TEST_F(ResourceCache_Test, AddResource) { + TestResource* resource = new TestResource("test1"); + ResourceGUID guid = resource->GetGUID(); + + m_cache->Add(guid, resource); + + EXPECT_EQ(m_cache->GetSize(), 1u); + EXPECT_EQ(m_cache->GetMemoryUsage(), resource->GetMemorySize()); +} + +TEST_F(ResourceCache_Test, FindResource) { + TestResource* resource = new TestResource("test1"); + ResourceGUID guid = resource->GetGUID(); + + m_cache->Add(guid, resource); + + IResource* found = m_cache->Find(guid); + EXPECT_EQ(found, resource); +} + +TEST_F(ResourceCache_Test, FindNonExistent) { + ResourceGUID guid(9999); + IResource* found = m_cache->Find(guid); + EXPECT_EQ(found, nullptr); +} + +TEST_F(ResourceCache_Test, RemoveResource) { + TestResource* resource = new TestResource("test1"); + ResourceGUID guid = resource->GetGUID(); + + m_cache->Add(guid, resource); + m_cache->Remove(guid); + + EXPECT_EQ(m_cache->GetSize(), 0u); + EXPECT_EQ(m_cache->Find(guid), nullptr); +} + +TEST_F(ResourceCache_Test, Touch_UpdatesAccessTime) { + TestResource* resource = new TestResource("test1"); + ResourceGUID guid = resource->GetGUID(); + + m_cache->Add(guid, resource); + m_cache->Touch(guid); + + // Touch后应能找到资源 + EXPECT_EQ(m_cache->Find(guid), resource); +} + +TEST_F(ResourceCache_Test, MemoryBudget) { + m_cache->SetMemoryBudget(1024); // 1KB + + EXPECT_EQ(m_cache->GetMemoryBudget(), 1024u); +} + +TEST_F(ResourceCache_Test, OnMemoryPressure_EvictUnreferenced) { + m_cache->SetMemoryBudget(512); + + // 添加多个资源 + for (int i = 0; i < 5; i++) { + TestResource* resource = new TestResource(Containers::String("test") + Containers::String::FromInt(i)); + m_cache->Add(resource->GetGUID(), resource); + } + + // 触发内存压力 + m_cache->OnMemoryPressure(1024); + + // 应该有资源被淘汰 + // 具体数量取决于LRU策略 +} + +TEST_F(ResourceCache_Test, Clear) { + for (int i = 0; i < 3; i++) { + TestResource* resource = new TestResource(Containers::String("test") + Containers::String::FromInt(i)); + m_cache->Add(resource->GetGUID(), resource); + } + + m_cache->Clear(); + + EXPECT_EQ(m_cache->GetSize(), 0u); + EXPECT_EQ(m_cache->GetMemoryUsage(), 0u); +} + +TEST_F(ResourceCache_Test, GetLRUList) { + // 添加资源并访问 + TestResource* r1 = new TestResource("test1"); + TestResource* r2 = new TestResource("test2"); + TestResource* r3 = new TestResource("test3"); + + m_cache->Add(r1->GetGUID(), r1); + m_cache->Add(r2->GetGUID(), r2); + m_cache->Add(r3->GetGUID(), r3); + + // 访问r1使其最新 + m_cache->Touch(r1->GetGUID()); + + auto lru = m_cache->GetLRUList(2); + + // r1应该是最新的,不应在LRU列表前几位 + EXPECT_GE(lru.Size(), 0u); +} + +} // namespace +``` + +### 12.5 第三阶段测试:异步加载(天6-7完成后) + +#### 测试 12.5.1 异步加载器测试 + +**文件**: `tests/Resources/test_async_loader.cpp` + +```cpp +#include +#include +#include "fixtures/ResourcesTestFixture.h" +#include + +using namespace XCEngine::Resources; + +namespace { + +class AsyncLoader_Test : public ResourcesTestFixture { +protected: + void SetUp() override { + ResourcesTestFixture::SetUp(); + } +}; + +TEST_F(AsyncLoader_Test, Submit_IncrementsPendingCount) { + AsyncLoader& loader = AsyncLoader::Get(); + + Core::uint32 pendingBefore = loader.GetPendingCount(); + + // 注意:需要先注册加载器,否则会立即失败 + // 这里测试API本身 + EXPECT_GE(pendingBefore, 0u); +} + +TEST_F(AsyncLoader_Test, Update_ProcessesCompletedRequests) { + AsyncLoader& loader = AsyncLoader::Get(); + + // 调用Update处理完成队列 + loader.Update(); + + // 不应崩溃 + EXPECT_TRUE(true); +} + +TEST_F(AsyncLoader_Test, IsLoading) { + AsyncLoader& loader = AsyncLoader::Get(); + + bool isLoading = loader.IsLoading(); + + EXPECT_FALSE(isLoading); // 初始状态 +} + +TEST_F(AsyncLoader_Test, GetProgress) { + AsyncLoader& loader = AsyncLoader::Get(); + + float progress = loader.GetProgress(); + + // 0.0 - 1.0之间 + EXPECT_GE(progress, 0.0f); + EXPECT_LE(progress, 1.0f); +} + +TEST_F(AsyncLoader_Test, CancelAll) { + AsyncLoader& loader = AsyncLoader::Get(); + + loader.CancelAll(); + + EXPECT_EQ(loader.GetPendingCount(), 0u); +} + +TEST_F(AsyncLoader_Test, CallbackInvocation) { + std::atomic callbackCount{0}; + + // 模拟回调 + auto callback = [&callbackCount](LoadResult result) { + callbackCount++; + }; + + // 调用Update确保没有pending请求 + AsyncLoader::Get().Update(); + + EXPECT_EQ(callbackCount, 0); +} + +} // namespace +``` + +### 12.6 第四阶段测试:具体资源类型(天8-11完成后) + +#### 测试 12.6.1 纹理资源测试 + +**文件**: `tests/Resources/test_texture.cpp` + +```cpp +#include +#include +#include +#include "fixtures/ResourcesTestFixture.h" + +using namespace XCEngine::Resources; + +namespace { + +class Texture_Test : public ResourcesTestFixture { +protected: + void SetUp() override { + ResourcesTestFixture::SetUp(); + } +}; + +TEST_F(Texture_Test, DefaultConstructor) { + Texture texture; + + EXPECT_FALSE(texture.IsValid()); + EXPECT_EQ(texture.GetType(), ResourceType::Texture); +} + +TEST_F(Texture_Test, GetDimensions_Default) { + Texture texture; + + EXPECT_EQ(texture.GetWidth(), 0u); + EXPECT_EQ(texture.GetHeight(), 0u); + EXPECT_EQ(texture.GetDepth(), 1u); + EXPECT_EQ(texture.GetMipLevels(), 1u); +} + +TEST_F(Texture_Test, GetTextureType_Default) { + Texture texture; + + EXPECT_EQ(texture.GetTextureType(), TextureType::Texture2D); +} + +TEST_F(Texture_Test, GetFormat_Default) { + Texture texture; + + EXPECT_EQ(texture.GetFormat(), TextureFormat::RGBA8_UNORM); +} + +TEST_F(Texture_Test, Create) { + Texture texture; + + bool result = texture.Create( + 256, 256, 1, 1, + TextureType::Texture2D, + TextureFormat::RGBA8_UNORM, + nullptr, 0 + ); + + EXPECT_TRUE(result); + EXPECT_EQ(texture.GetWidth(), 256u); + EXPECT_EQ(texture.GetHeight(), 256u); + EXPECT_TRUE(texture.IsValid()); +} + +TEST_F(Texture_Test, CreateWithMipmaps) { + Texture texture; + + bool result = texture.Create( + 256, 256, 1, 4, + TextureType::Texture2D, + TextureFormat::RGBA8_UNORM, + nullptr, 0 + ); + + EXPECT_TRUE(result); + EXPECT_EQ(texture.GetMipLevels(), 4u); +} + +TEST_F(Texture_Test, GetMemorySize) { + Texture texture; + + // 256x256 RGBA8 = 256*256*4 = 262144 bytes + texture.Create(256, 256, 1, 1, TextureType::Texture2D, + TextureFormat::RGBA8_UNORM, nullptr, 0); + + size_t memorySize = texture.GetMemorySize(); + EXPECT_GT(memorySize, 0u); +} + +TEST_F(Texture_Test, GetName) { + Texture texture; + ConstructParams params; + params.name = "TestTexture"; + params.path = "textures/test.png"; + params.guid = ResourceGUID::Generate("test"); + params.memorySize = 1024; + texture.Initialize(params); + + EXPECT_STREQ(texture.GetName().CStr(), "TestTexture"); +} + +TEST_F(Texture_Test, GetPath) { + Texture texture; + ConstructParams params; + params.name = "TestTexture"; + params.path = "textures/test.png"; + params.guid = ResourceGUID::Generate("test"); + params.memorySize = 1024; + texture.Initialize(params); + + EXPECT_STREQ(texture.GetPath().CStr(), "textures/test.png"); +} + +TEST_F(Texture_Test, TextureLoader_CanLoad) { + TextureLoader loader; + + EXPECT_TRUE(loader.CanLoad("textures/test.png")); + EXPECT_TRUE(loader.CanLoad("textures/test.jpg")); + EXPECT_TRUE(loader.CanLoad("textures/test.tga")); + EXPECT_FALSE(loader.CanLoad("models/test.obj")); +} + +TEST_F(Texture_Test, TextureLoader_GetSupportedExtensions) { + TextureLoader loader; + auto extensions = loader.GetSupportedExtensions(); + + EXPECT_GE(extensions.Size(), 5u); +} + +TEST_F(Texture_Test, TextureLoader_GetResourceType) { + TextureLoader loader; + + EXPECT_EQ(loader.GetResourceType(), ResourceType::Texture); +} + +TEST_F(Texture_Test, TextureLoader_GetDefaultSettings) { + TextureLoader loader; + ImportSettings* settings = loader.GetDefaultSettings(); + + EXPECT_NE(settings, nullptr); + EXPECT_TRUE(dynamic_cast(settings) != nullptr); + + delete settings; +} + +TEST_F(Texture_Test, TextureImportSettings_Defaults) { + TextureImportSettings settings; + + EXPECT_EQ(settings.GetTextureType(), TextureType::Texture2D); + EXPECT_TRUE(settings.GetGenerateMipmaps()); + EXPECT_EQ(settings.GetMaxAnisotropy(), 16u); +} + +TEST_F(Texture_Test, TextureImportSettings_Modify) { + TextureImportSettings settings; + + settings.SetTextureType(TextureType::TextureCube); + settings.SetGenerateMipmaps(false); + settings.SetMaxAnisotropy(8); + settings.SetSRGB(true); + + EXPECT_EQ(settings.GetTextureType(), TextureType::TextureCube); + EXPECT_FALSE(settings.GetGenerateMipmaps()); + EXPECT_EQ(settings.GetMaxAnisotropy(), 8u); + EXPECT_TRUE(settings.GetSRGB()); +} + +} // namespace +``` + +#### 测试 12.6.2 网格资源测试 + +**文件**: `tests/Resources/test_mesh.cpp` + +```cpp +#include +#include +#include "fixtures/ResourcesTestFixture.h" + +using namespace XCEngine::Resources; + +namespace { + +class Mesh_Test : public ResourcesTestFixture {}; + +TEST_F(Mesh_Test, DefaultConstructor) { + Mesh mesh; + + EXPECT_FALSE(mesh.IsValid()); + EXPECT_EQ(mesh.GetType(), ResourceType::Mesh); +} + +TEST_F(Mesh_Test, GetVertexCount_Default) { + Mesh mesh; + + EXPECT_EQ(mesh.GetVertexCount(), 0u); +} + +TEST_F(Mesh_Test, GetIndexCount_Default) { + Mesh mesh; + + EXPECT_EQ(mesh.GetIndexCount(), 0u); +} + +TEST_F(Mesh_Test, SetVertexData) { + Mesh mesh; + + // 简单顶点数据:位置 + float vertices[] = { + 0.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f + }; + + mesh.SetVertexData(vertices, sizeof(vertices), 3, 12, VertexAttribute::Position); + + EXPECT_EQ(mesh.GetVertexCount(), 3u); + EXPECT_EQ(mesh.GetVertexStride(), 12u); + EXPECT_TRUE(mesh.GetVertexAttributes() & VertexAttribute::Position); +} + +TEST_F(Mesh_Test, SetIndexData) { + Mesh mesh; + + // 三角形索引 + uint16_t indices[] = {0, 1, 2}; + + mesh.SetIndexData(indices, sizeof(indices), 3, false); + + EXPECT_EQ(mesh.GetIndexCount(), 3u); + EXPECT_FALSE(mesh.IsUse32BitIndex()); +} + +TEST_F(Mesh_Test, SetIndexData_32Bit) { + Mesh mesh; + + uint32_t indices[] = {0, 1, 2, 0, 2, 3}; + + mesh.SetIndexData(indices, sizeof(indices), 6, true); + + EXPECT_EQ(mesh.GetIndexCount(), 6u); + EXPECT_TRUE(mesh.IsUse32BitIndex()); +} + +TEST_F(Mesh_Test, AddSection) { + Mesh mesh; + + MeshSection section; + section.baseVertex = 0; + section.vertexCount = 3; + section.startIndex = 0; + section.indexCount = 3; + section.materialID = 0; + + mesh.AddSection(section); + + EXPECT_EQ(mesh.GetSections().Size(), 1u); +} + +TEST_F(Mesh_Test, BoundingBox) { + Mesh mesh; + + Math::AABB box; + box.Min = Math::Vector3(0, 0, 0); + box.Max = Math::Vector3(1, 1, 1); + + mesh.SetBoundingBox(box); + + EXPECT_EQ(mesh.GetBoundingBox().Min, Math::Vector3(0, 0, 0)); + EXPECT_EQ(mesh.GetBoundingBox().Max, Math::Vector3(1, 1, 1)); +} + +TEST_F(Mesh_Test, VertexAttribute_Enum) { + // 测试顶点属性标志 + VertexAttribute attrs = VertexAttribute::Position | VertexAttribute::Normal | VertexAttribute::UV0; + + EXPECT_TRUE(attrs & VertexAttribute::Position); + EXPECT_TRUE(attrs & VertexAttribute::Normal); + EXPECT_TRUE(attrs & VertexAttribute::UV0); + EXPECT_FALSE(attrs & VertexAttribute::Tangent); +} + +} // namespace +``` + +#### 测试 12.6.3 材质资源测试 + +**文件**: `tests/Resources/test_material.cpp` + +```cpp +#include +#include +#include "fixtures/ResourcesTestFixture.h" + +using namespace XCEngine::Resources; + +namespace { + +class Material_Test : public ResourcesTestFixture {}; + +TEST_F(Material_Test, DefaultConstructor) { + Material material; + + EXPECT_FALSE(material.IsValid()); + EXPECT_EQ(material.GetType(), ResourceType::Material); +} + +TEST_F(Material_Test, SetFloat) { + Material material; + + material.SetFloat("Metallic", 0.5f); + + EXPECT_FLOAT_EQ(material.GetFloat("Metallic"), 0.5f); +} + +TEST_F(Material_Test, SetFloat2) { + Material material; + + material.SetFloat2("UVScale", Math::Vector2(2.0f, 3.0f)); + + Math::Vector2 value = material.GetFloat2("UVScale"); + EXPECT_FLOAT_EQ(value.x, 2.0f); + EXPECT_FLOAT_EQ(value.y, 3.0f); +} + +TEST_F(Material_Test, SetFloat3) { + Material material; + + material.SetFloat3("Albedo", Math::Vector3(1.0f, 0.0f, 0.0f)); + + Math::Vector3 value = material.GetFloat3("Albedo"); + EXPECT_FLOAT_EQ(value.x, 1.0f); + EXPECT_FLOAT_EQ(value.y, 0.0f); + EXPECT_FLOAT_EQ(value.z, 0.0f); +} + +TEST_F(Material_Test, SetFloat4) { + Material material; + + material.SetFloat4("Color", Math::Vector4(1.0f, 1.0f, 1.0f, 0.5f)); + + Math::Vector4 value = material.GetFloat4("Color"); + EXPECT_FLOAT_EQ(value.w, 0.5f); +} + +TEST_F(Material_Test, SetInt) { + Material material; + + material.SetInt("RenderQueue", 2000); + + EXPECT_EQ(material.GetInt("RenderQueue"), 2000); +} + +TEST_F(Material_Test, SetBool) { + Material material; + + material.SetBool("EnableInstancing", true); + + EXPECT_TRUE(material.GetBool("EnableInstancing")); +} + +TEST_F(Material_Test, SetTexture) { + Material material; + + // 创建测试纹理 + Texture* tex = new Texture(); + tex->Initialize({"TestTex", "test.png", ResourceGUID::Generate("test"), 1024}); + + ResourceHandle handle(tex); + material.SetTexture("MainTex", handle); + + // 验证纹理设置成功 + // 注意:需要实现GetTexture方法 +} + +TEST_F(Material_Test, PropertyNotFound) { + Material material; + + // 查询不存在的属性应有默认值 + EXPECT_FLOAT_EQ(material.GetFloat("NonExistent"), 0.0f); +} + +} // namespace +``` + +### 12.7 第五阶段测试:资源管理器(天3-5完成后) + +#### 测试 12.7.1 资源管理器测试 + +**文件**: `tests/Resources/test_resource_manager.cpp` + +```cpp +#include +#include +#include "fixtures/ResourcesTestFixture.h" + +using namespace XCEngine::Resources; + +namespace { + +class ResourceManager_Test : public ResourcesTestFixture {}; + +TEST_F(ResourceManager_Test, GetSingleton) { + ResourceManager& manager = ResourceManager::Get(); + + EXPECT_EQ(&manager, &ResourceManager::Get()); +} + +TEST_F(ResourceManager_Test, SetResourceRoot) { + ResourceManager& manager = ResourceManager::Get(); + + manager.SetResourceRoot("resources/"); + + EXPECT_STREQ(manager.GetResourceRoot().CStr(), "resources/"); +} + +TEST_F(ResourceManager_Test, SetMemoryBudget) { + ResourceManager& manager = ResourceManager::Get(); + + manager.SetMemoryBudget(1024 * 1024); // 1MB + + EXPECT_EQ(manager.GetMemoryBudget(), 1024u * 1024u); +} + +TEST_F(ResourceManager_Test, GetMemoryUsage_Initial) { + ResourceManager& manager = ResourceManager::Get(); + + EXPECT_EQ(manager.GetMemoryUsage(), 0u); +} + +TEST_F(ResourceManager_Test, RegisterLoader) { + ResourceManager& manager = ResourceManager::Get(); + + // 纹理加载器应该已经注册 + IResourceLoader* loader = manager.GetLoader(ResourceType::Texture); + EXPECT_NE(loader, nullptr); +} + +TEST_F(ResourceManager_Test, GetLoader_NotFound) { + ResourceManager& manager = ResourceManager::Get(); + + IResourceLoader* loader = manager.GetLoader(ResourceType::Unknown); + EXPECT_EQ(loader, nullptr); +} + +TEST_F(ResourceManager_Test, AddRef_Release) { + ResourceGUID guid(12345); + + ResourceManager::Get().AddRef(guid); + EXPECT_EQ(ResourceManager::Get().GetRefCount(guid), 1u); + + ResourceManager::Get().AddRef(guid); + EXPECT_EQ(ResourceManager::Get().GetRefCount(guid), 2u); + + ResourceManager::Get().Release(guid); + EXPECT_EQ(ResourceManager::Get().GetRefCount(guid), 1u); + + ResourceManager::Get().Release(guid); + // 引用计数为0时应返回0 +} + +TEST_F(ResourceManager_Test, UnloadAll) { + ResourceManager& manager = ResourceManager::Get(); + + // 添加一些引用 + ResourceGUID guid1(100); + ResourceGUID guid2(200); + manager.AddRef(guid1); + manager.AddRef(guid2); + + manager.UnloadAll(); + + // 所有引用计数应被清除 + EXPECT_EQ(manager.GetRefCount(guid1), 0u); + EXPECT_EQ(manager.GetRefCount(guid2), 0u); +} + +TEST_F(ResourceManager_Test, Exists) { + ResourceManager& manager = ResourceManager::Get(); + + // 未加载的资源应返回false + EXPECT_FALSE(manager.Exists("nonexistent.png")); +} + +TEST_F(ResourceManager_Test, ResolvePath) { + ResourceManager& manager = ResourceManager::Get(); + manager.SetResourceRoot("myresources/"); + + Containers::String resolved = manager.ResolvePath("textures/test.png"); + + EXPECT_STREQ(resolved.CStr(), "myresources//textures/test.png"); +} + +} // namespace +``` + +### 12.8 测试运行脚本 + +**文件**: `tests/Resources/run_tests.bat` + +```bat +@echo off +echo ======================================== +echo XCEngine Resources System Tests +echo ======================================== + +cd /d %~dp0\..\..\build +if exist "tests\Resources\xcengine_resources_tests.exe" ( + echo Running Resources tests... + tests\Resources\xcengine_resources_tests.exe + + if %ERRORLEVEL% EQU 0 ( + echo. + echo [SUCCESS] All resource tests passed! + ) else ( + echo. + echo [FAILED] Some tests failed! + exit /b 1 + ) +) else ( + echo Error: Test executable not found! + echo Please build the project first. + exit /b 1 +) +``` + +### 12.9 测试CMakeLists.txt + +**文件**: `tests/Resources/CMakeLists.txt` + +```cmake +# ============================================================ +# Resources Library Tests +# ============================================================ + +set(RESOURCES_TEST_SOURCES + test_resource_types.cpp + test_resource_guid.cpp + test_iresource.cpp + test_resource_handle.cpp + test_resource_cache.cpp + test_async_loader.cpp + test_texture.cpp + test_mesh.cpp + test_material.cpp + test_audio_clip.cpp + test_resource_manager.cpp + test_resource_filesystem.cpp + test_resource_dependency.cpp +) + +add_executable(xcengine_resources_tests ${RESOURCES_TEST_SOURCES}) + +if(MSVC) + set_target_properties(xcengine_resources_tests PROPERTIES + LINK_FLAGS "/NODEFAULTLIB:libcpmt.lib /NODEFAULTLIB:libcmt.lib" + ) +endif() + +target_link_libraries(xcengine_resources_tests + PRIVATE + XCEngine + GTest::gtest + GTest::gtest_main +) + +target_include_directories(xcengine_resources_tests PRIVATE + ${CMAKE_SOURCE_DIR}/engine/include + ${CMAKE_SOURCE_DIR}/tests/fixtures + ${CMAKE_SOURCE_DIR}/tests/Resources/fixtures +) + +# 复制测试数据到输出目录 +file(COPY ${CMAKE_SOURCE_DIR}/tests/Resources/test_data + DESTINATION ${CMAKE_BINARY_DIR}/tests/Resources/) + +add_test(NAME ResourcesTests COMMAND xcengine_resources_tests) +``` + +### 12.10 阶段测试验收清单 + +每个阶段完成后,运行对应测试验证功能正确性: + +| 阶段 | 完成后运行测试 | 验收标准 | +|------|---------------|----------| +| **天1-3: 基础框架** | `test_resource_types.cpp`
`test_resource_guid.cpp`
`test_resource_handle.cpp` | ✅ ResourceType枚举正确
✅ GUID生成稳定
✅ 句柄引用计数正确 | +| **天4-5: 缓存系统** | `test_resource_cache.cpp` | ✅ LRU淘汰正常
✅ 内存预算生效
✅ 内存压力响应 | +| **天6-7: 异步加载** | `test_async_loader.cpp` | ✅ 任务提交正常
✅ 回调正常
✅ 进度计算正确 | +| **天8-9: 纹理** | `test_texture.cpp` | ✅ 创建/设置属性正常
✅ 加载器识别格式
✅ 导入设置生效 | +| **天10: 网格** | `test_mesh.cpp` | ✅ 顶点/索引数据正常
✅ 子网格正常
✅ 包围盒正常 | +| **天11: 材质** | `test_material.cpp` | ✅ 属性设置/获取正常
✅ 类型转换正确 | +| **天12-13: 文件系统** | `test_resource_filesystem.cpp` | ✅ 目录遍历正常
✅ 归档加载正常 | +| **天14-15: 依赖管理** | `test_resource_dependency.cpp` | ✅ 依赖关系正确
✅ 循环检测正常 | +| **天16-17: 集成** | 全部测试 | ✅ 所有测试通过
✅ 内存无泄漏 | + +### 12.11 每日测试执行流程 + +```bash +# 每天完成代码后,在build目录执行: +cd build + +# 编译测试 +cmake --build . --target xcengine_resources_tests + +# 运行当天相关测试 +ctest -R "Resources_类型名" -V + +# 例如: +# 第3天完成后运行: +ctest -R "Resources_Types|Resources_GUID|Resources_Handle" -V + +# 第5天完成后运行: +ctest -R "Resources_Cache" -V + +# 全部测试通过后进行下一阶段 +``` + +### 12.12 测试数据准备 + +需要在 `tests/Resources/test_data/` 目录下准备以下测试文件: + +``` +test_data/ +├── textures/ +│ ├── test_256x256.png # 256x256 PNG测试纹理 +│ ├── test_512x512.jpg # 512x512 JPG测试纹理 +│ └── test_red.tga # 纯红色TGA +├── models/ +│ ├── cube.obj # 简单立方体 +│ ├── sphere.obj # 球体 +│ └── plane.obj # 平面 +├── materials/ +│ ├── test_material.json # 测试材质 +│ └── test_pbr.json # PBR材质 +├── audio/ +│ ├── test_mono.wav # 单声道WAV +│ └── test_stereo.wav # 立体声WAV +└── archives/ + └── test.xcrap # 测试资源包 +``` + +--- + +## 13. 关键技术点 + +### 13.1 引用计数与缓存淘汰的交互 + +```cpp +// 引用计数管理 +void ResourceManager::AddRef(ResourceGUID guid) { + std::lock_guard lock(m_mutex); + + // 增加引用计数 + auto it = m_refCounts.Find(guid); + if (it == m_refCounts.End()) { + m_refCounts.Insert(guid, 1); + } else { + it->second++; + } + + // 确保资源在缓存中 + if (!m_resourceCache.Contains(guid)) { + // 重新加载资源 + ReloadResource(guid); + } +} + +void ResourceManager::Release(ResourceGUID guid) { + std::lock_guard lock(m_mutex); + + auto it = m_refCounts.Find(guid); + if (it != m_refCounts.End()) { + it->second--; + + // 引用计数为0时,不立即卸载 + // 由缓存系统根据LRU策略决定何时卸载 + if (it->second == 0) { + m_refCounts.Erase(guid); + // 通知缓存系统资源可以淘汰 + m_cache.OnZeroRefCount(guid); + } + } +} +``` + +### 13.2 异步加载线程安全 + +```cpp +// AsyncLoader::Update() 在主线程调用 +void AsyncLoader::Update() { + // 1. 从完成队列取出结果(线程安全) + Array completed; + { + std::lock_guard lock(m_completedMutex); + completed = std::move(m_completedQueue); + m_completedQueue.Clear(); + } + + // 2. 在主线程处理完成回调 + for (auto& request : completed) { + if (request.callback) { + // 回调中可能创建ResourceHandle,增加引用计数 + request.callback(m_result); + } + } +} + +// 工作线程函数 +void LoadTask::Execute() { + // 在工作线程执行实际加载 + m_result = m_loader->Load(m_request.path, m_request.settings.get()); + + // 放入完成队列 + AsyncLoader::Get().QueueCompleted(std::move(m_request), std::move(m_result)); +} +``` + +### 13.3 内存压力响应 + +```cpp +void ResourceCache::OnMemoryPressure(size_t requiredBytes) { + std::lock_guard lock(m_mutex); + + if (m_memoryUsage + requiredBytes <= m_memoryBudget) { + return; // 内存充足 + } + + // 需要释放内存 + size_t targetRelease = (m_memoryUsage + requiredBytes) - m_memoryBudget; + + // 按LRU顺序淘汰 + for (auto it = m_lruOrder.Begin(); it != m_lruOrder.End() && targetRelease > 0; ) { + ResourceGUID guid = *it; + auto cacheIt = m_cache.Find(guid); + + if (cacheIt != m_cache.End()) { + CacheEntry& entry = cacheIt->second; + + // 检查是否有外部引用 + if (ResourceManager::Get().GetRefCount(guid) == 0) { + size_t releasedSize = entry.memorySize; + + // 从缓存移除 + m_cache.Erase(guid); + m_memoryUsage -= releasedSize; + targetRelease -= releasedSize; + + // 销毁资源 + entry.resource->Release(); + + // 从LRU列表移除 + it = m_lruOrder.Erase(it); + } else { + ++it; // 有外部引用,跳过 + } + } else { + ++it; + } + } +} +``` + +--- + +## 14. 使用示例 + +### 14.1 基本使用 + +```cpp +// 初始化资源系统 +void InitResourceSystem() { + // 设置资源根目录 + ResourceManager::Get().SetResourceRoot("resources/"); + + // 初始化异步加载器(2个工作线程) + AsyncLoader::Get().Initialize(2); + + // 设置内存预算(1GB) + ResourceManager::Get().SetMemoryBudget(1024 * 1024 * 1024); +} + +// 同步加载纹理 +void LoadTextureExample() { + // 加载纹理 + ResourceHandle tex = ResourceManager::Get().Load("textures/player.png"); + + if (tex.IsValid()) { + // 使用纹理 + Texture* texture = tex.Get(); + printf("Loaded texture: %s, %dx%d\n", + tex->GetName().CStr(), + texture->GetWidth(), + texture->GetHeight()); + + // 传递给渲染器 + renderer->SetTexture(0, texture->GetRHIResource()); + } + + // 离开作用域时自动释放(引用计数-1) +} + +// 异步加载网格 +void LoadMeshAsyncExample() { + ResourceManager::Get().LoadAsync("models/player.fbx", ResourceType::Mesh, + [](LoadResult result) { + if (result && result.resource) { + // 在主线程回调中处理 + // 注意:需要手动转换为正确的类型 + Mesh* mesh = static_cast(result.resource); + printf("Mesh loaded: %s\n", mesh->GetName().CStr()); + + // 添加到场景 + // 注意:这里需要创建ResourceHandle来管理生命周期 + ResourceHandle meshHandle(mesh); + scene->AddMesh(meshHandle); + } else { + printf("Failed to load mesh: %s\n", result.errorMessage.CStr()); + } + }); + + // 异步加载进行中... + // 主线程继续执行其他逻辑 +} +``` + +### 14.2 资源组加载 + +```cpp +// 加载场景所需的所有资源 +void LoadSceneResources(const String& scenePath) { + // 1. 加载场景配置文件 + String sceneConfigPath = "scenes/" + scenePath + ".scene"; + ResourceHandle sceneConfig = + ResourceManager::Get().Load(sceneConfigPath); + + // 2. 解析配置文件获取依赖列表 + Array dependencies = ParseSceneDependencies(sceneConfig.Get()); + + // 3. 异步加载所有依赖 + Core::uint32 totalResources = dependencies.Size(); + Core::uint32 loadedCount = 0; + + for (const auto& dep : dependencies) { + // 根据扩展名判断资源类型 + String ext = Path::GetExtension(dep); + ResourceType type = ResourceType::Binary; // 默认 + + if (ext == ".png" || ext == ".jpg") { + type = ResourceType::Texture; + } else if (ext == ".fbx" || ext == ".obj") { + type = ResourceType::Mesh; + } + // ... 其他类型 + + ResourceManager::Get().LoadAsync(dep, type, + [&loadedCount, totalResources](LoadResult result) { + loadedCount++; + printf("Loading progress: %d/%d\n", loadedCount, totalResources); + }); + } +} +``` + +### 14.3 自定义导入设置 + +```cpp +void LoadTextureWithSettings() { + // 创建导入设置 + TextureImportSettings* settings = new TextureImportSettings(); + settings->SetGenerateMipmaps(true); + settings->SetSRGB(true); + settings->SetTargetFormat(TextureFormat::BC7_UNORM); + settings->SetMaxAnisotropy(16); + + // 加载时传入设置 + ResourceHandle tex = ResourceManager::Get().Load( + "textures/diffuse.png", settings); + + // settings由ResourceManager管理,不需要手动delete +} +``` + +--- + +## 15. 验收标准 + +### 13.1 功能验收 + +- [ ] 能够通过路径加载Texture资源(PNG, JPG, TGA) +- [ ] 能够通过路径加载Mesh资源(OBJ, glTF) +- [ ] 能够通过路径加载Material资源(JSON格式) +- [ ] 能够通过路径加载AudioClip资源(WAV格式) +- [ ] 异步加载功能正常工作,回调在主线程执行 +- [ ] 资源缓存机制正常工作,LRU淘汰策略生效 +- [ ] 引用计数正确管理,零引用时资源可被淘汰 +- [ ] 内存预算控制正常工作,超出预算时自动淘汰资源 + +### 13.2 性能验收 + +- [ ] 缓存命中时资源加载时间为0 +- [ ] 异步加载不阻塞主线程 +- [ ] 多线程加载时无数据竞争 +- [ ] 内存使用稳定,无内存泄漏 + +### 13.3 代码质量 + +- [ ] 编译通过,无警告 +- [ ] 遵循项目编码规范 +- [ ] 必要的注释和文档 +- [ ] 错误处理完善 + +--- + +## 16. 后续扩展 + +### 14.1 可选的扩展功能 + +| 功能 | 说明 | 工作量 | +|------|------|--------| +| **资源热加载** | 编辑器中修改资源后实时更新 | 2天 | +| **资源版本控制** | 检测资源变化,自动重新加载 | 2天 | +| **资源加密** | 支持加密的资源包 | 1天 | +| **资源流式加载** | 大资源分块加载 | 3天 | +| **资源分析器** | 可视化资源使用情况 | 2天 | + +### 14.2 资源格式扩展 + +| 格式 | 说明 | 优先级 | +|------|------|--------| +| glTF 2.0 | 现代3D模型格式,高优先级 | P0 | +| DDS | 压缩纹理格式 | P0 | +| OGG/Vorbis | 压缩音频格式 | P1 | +| PSD | Photoshop源文件 | P2 | +| EXR | HDR图像 | P2 | + +--- + +## 17. 依赖关系 + +``` +资源系统依赖关系图: + +第一阶段基础层 + │ + ├── Math Library ─────┐ + │ │ + ├── Containers ──────┼──► 资源系统 + │ │ + ├── Memory ────────┤ + │ │ + └── Threading ─────────┘ + │ + ▼ + ┌─────────────────┐ + │ AsyncLoader │ (依赖TaskSystem) + └────────┬────────┘ + │ + ┌────────▼────────┐ + │ ResourceManager │ + └────────┬────────┘ + │ + ┌────────▼────────┐ ┌─────────────┐ + │ ResourceCache │────►│ 引用计数 │ + └────────┬────────┘ │ 管理 │ + │ └─────────────┘ + ┌────────▼────────┐ + │ ResourceLoader │ + └────────┬────────┘ + │ + ┌────────▼────────┐ + │ 具体资源类型 │ + │ (Texture等) │ + └─────────────────┘ +``` + +--- + +*文档版本: 1.0* +*更新日期: 2026-03-17* diff --git a/electron/main.mjs b/electron/main.mjs index 093fb85..1c6f655 100644 --- a/electron/main.mjs +++ b/electron/main.mjs @@ -7,7 +7,9 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); let mainWindow = null; -const LOG_FILE = path.join(__dirname, '..', 'electron.log'); +const LOG_FILE = app.isPackaged + ? path.join(app.getPath('userData'), 'electron.log') + : path.join(__dirname, '..', 'electron.log'); function log(...args) { const msg = args.map(a => typeof a === 'object' ? JSON.stringify(a) : String(a)).join(' '); diff --git a/src/components/ApiDocViewer.tsx b/src/components/ApiDocViewer.tsx index 5f30ad5..09788d0 100644 --- a/src/components/ApiDocViewer.tsx +++ b/src/components/ApiDocViewer.tsx @@ -107,9 +107,10 @@ export const ApiDocViewer = ({ onDocsPathChange, showAddModal, onCloseAddModal } const handleFolderClick = useCallback((folderPath: string) => { const parts = folderPath.split('/') const basename = parts[parts.length - 1] - const sameNameDoc = externalDocs.find(d => - d.relativePath.endsWith(`/${basename}.md`) - ) + + // 使用精确路径匹配:目标文件必须在 folderPath 目录下,且名为 basename.md + const targetPath = `${folderPath}/${basename}.md` + const sameNameDoc = externalDocs.find(d => d.relativePath === targetPath) if (sameNameDoc) { setSelectedPath(sameNameDoc.relativePath) @@ -128,16 +129,50 @@ export const ApiDocViewer = ({ onDocsPathChange, showAddModal, onCloseAddModal } } const handleReferenceClick = useCallback((href: string) => { - const ref = href.replace(/\.md$/, '') - const match = externalDocs.find(d => { - const docPath = d.relativePath.replace(/\.md$/, '') - return docPath === ref || docPath.endsWith('/' + ref.split('/').pop()) - }) + if (!selectedPath) return + + // 1. 获取当前文档所在的目录 + const currentDir = selectedPath.split('/').slice(0, -1) + + // 2. 解析目标路径 + let targetParts: string[] = [] + + if (href.startsWith('/')) { + // 绝对路径(相对于文档根目录) + const pathStr = href.slice(1) + targetParts = pathStr ? pathStr.split('/') : [] + } else { + // 相对路径处理 + targetParts = [...currentDir] + const hrefParts = href.split('/') + + for (const part of hrefParts) { + if (part === '.') continue + if (part === '..') { + targetParts.pop() + } else { + targetParts.push(part) + } + } + } + + let targetPath = targetParts.join('/') + + // 3. 规范化目标路径(确保包含 .md) + if (!targetPath.endsWith('.md')) { + targetPath += '.md' + } + + // 4. 精确查找 + const match = externalDocs.find(d => d.relativePath === targetPath) + if (match) { setSelectedPath(match.relativePath) setCurrentContent(match.content) + } else { + console.warn(`Document not found: ${targetPath}`) } - }, [externalDocs]) + }, [externalDocs, selectedPath]) return (
diff --git a/src/components/DocContent.tsx b/src/components/DocContent.tsx index f9c1f53..d9dde02 100644 --- a/src/components/DocContent.tsx +++ b/src/components/DocContent.tsx @@ -18,18 +18,29 @@ export const DocContent = ({ content, onReferenceClick }: DocContentProps) => { const components: Components = { a: ({ href, children }) => { - if (href && (href.startsWith('./') || href.startsWith('../'))) { + const isInternal = href && !href.startsWith('http') && !href.startsWith('mailto:') && !href.startsWith('#'); + + if (isInternal) { return ( - + ) } return ( - + {children} ) diff --git a/src/components/DocTree.tsx b/src/components/DocTree.tsx index c87ba8d..eb7943c 100644 --- a/src/components/DocTree.tsx +++ b/src/components/DocTree.tsx @@ -35,7 +35,8 @@ const TreeNode = React.memo(({ }: TreeNodeProps) => { const isDir = file.isDir const isExpanded = expandedSet.has(file.relativePath) - const isSelected = selectedPath === file.relativePath + const isSelected = selectedPath === file.relativePath || + (isDir && selectedPath === `${file.relativePath}/${file.name}.md`) const handleClick = () => { if (isDir) { @@ -59,7 +60,8 @@ const TreeNode = React.memo(({ return level * 3 + 3 } - const showChildren = isDir && isExpanded && file.children + const visibleChildren = file.children?.filter(c => c.isDir) + const showChildren = isDir && isExpanded && visibleChildren && visibleChildren.length > 0 return ( <> @@ -88,12 +90,12 @@ const TreeNode = React.memo(({
- {showChildren && file.children!.map((child, idx) => ( + {showChildren && visibleChildren!.map((child, idx) => ( f.isDir) + return (
- {files.map((file, idx) => ( + {visibleFiles.map((file, idx) => (