diff --git a/.github/update.log b/.github/update.log index 83118171b3..0ccee38ac2 100644 --- a/.github/update.log +++ b/.github/update.log @@ -652,3 +652,4 @@ Update On Thu May 16 20:28:24 CEST 2024 Update On Fri May 17 20:29:52 CEST 2024 Update On Sat May 18 20:30:29 CEST 2024 Update On Sun May 19 20:28:25 CEST 2024 +Update On Mon May 20 20:29:32 CEST 2024 diff --git a/clash-meta/.github/workflows/build.yml b/clash-meta/.github/workflows/build.yml index 84536a547b..42023755e1 100644 --- a/clash-meta/.github/workflows/build.yml +++ b/clash-meta/.github/workflows/build.yml @@ -18,7 +18,7 @@ on: branches: - Alpha concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true env: @@ -270,7 +270,7 @@ jobs: - name: Archive production artifacts uses: actions/upload-artifact@v4 with: - name: ${{ matrix.jobs.goos }}-${{ matrix.jobs.output }} + name: "${{ matrix.jobs.goos }}-${{ matrix.jobs.output }}" path: | mihomo*.gz mihomo*.deb @@ -415,35 +415,35 @@ jobs: uses: docker/setup-buildx-action@v3 with: version: latest - - - name: Set Docker tags and labels based on trigger - id: set-meta - run: | - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - echo "tags=${{ github.event.inputs.version }}" >> $GITHUB_ENV - echo "labels=org.opencontainers.image.version=${{ github.event.inputs.version }}" >> $GITHUB_ENV - else - echo "tags=${{ steps.meta.outputs.tags }}" >> $GITHUB_ENV - echo "labels=${{ steps.meta.outputs.labels }}" >> $GITHUB_ENV - fi - - + # Extract metadata (tags, labels) for Docker # https://github.com/docker/metadata-action - name: Extract Docker metadata - id: meta + if: ${{ github.event_name != 'workflow_dispatch' }} + id: meta_alpha uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ github.repository }} - tags: ${{ env.tags }} - labels: ${{ env.labels }} - - + images: '${{ env.REGISTRY }}/${{ github.repository }}' + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' }} + id: meta_release + uses: docker/metadata-action@v5 + with: + images: '${{ env.REGISTRY }}/${{ github.repository }}' + tags: | + ${{ github.event.inputs.version }} + flavor: | + latest=true + labels: org.opencontainers.image.version=${{ github.event.inputs.version }} + - name: Show files run: | ls . ls bin/ - + - name: login to docker REGISTRY uses: docker/login-action@v3 with: @@ -454,7 +454,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - id: build-and-push + if: ${{ github.event_name != 'workflow_dispatch' }} uses: docker/build-push-action@v5 with: context: . @@ -465,5 +465,20 @@ jobs: linux/amd64 linux/arm64 linux/arm/v7 - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file + tags: ${{ steps.meta_alpha.outputs.tags }} + labels: ${{ steps.meta_alpha.outputs.labels }} + + - name: Build and push Docker image + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' }} + uses: docker/build-push-action@v5 + with: + context: . + file: ./Dockerfile + push: ${{ github.event_name != 'pull_request' }} + platforms: | + linux/386 + linux/amd64 + linux/arm64 + linux/arm/v7 + tags: ${{ steps.meta_release.outputs.tags }} + labels: ${{ steps.meta_release.outputs.labels }} \ No newline at end of file diff --git a/clash-meta/go.mod b/clash-meta/go.mod index d9ed12289b..601929c189 100644 --- a/clash-meta/go.mod +++ b/clash-meta/go.mod @@ -19,7 +19,7 @@ require ( github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 github.com/mdlayher/netlink v1.7.2 github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 - github.com/metacubex/quic-go v0.43.2-0.20240518033621-2c3d14c6b38e + github.com/metacubex/quic-go v0.44.1-0.20240520163451-20b689a59136 github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72 github.com/metacubex/sing-shadowsocks v0.2.6 github.com/metacubex/sing-shadowsocks2 v0.2.0 diff --git a/clash-meta/go.sum b/clash-meta/go.sum index fb14d71525..091f6cf126 100644 --- a/clash-meta/go.sum +++ b/clash-meta/go.sum @@ -104,8 +104,8 @@ github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvO github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88= github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec h1:HxreOiFTUrJXJautEo8rnE1uKTVGY8wtZepY1Tii/Nc= github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw= -github.com/metacubex/quic-go v0.43.2-0.20240518033621-2c3d14c6b38e h1:Nzwe08FNIJpExWpy9iXkG336dN/8nJqn69yijB7vJ8g= -github.com/metacubex/quic-go v0.43.2-0.20240518033621-2c3d14c6b38e/go.mod h1:uXHODgJFUfUnkkCMWLd5Er6L5QY/LFRZb9LD5jyyhsk= +github.com/metacubex/quic-go v0.44.1-0.20240520163451-20b689a59136 h1:Z9XGYDs6QuSqipNcxbTx+baN/bBBAIpRxVhLpoMF42U= +github.com/metacubex/quic-go v0.44.1-0.20240520163451-20b689a59136/go.mod h1:88wAATpevav4xdy5N8oejQ2cbbI6EcLYEklFeo+qywA= github.com/metacubex/sing v0.0.0-20240518125217-e63d65a914d1 h1:7hDHLTmjgtRoAp59STwPQpe5Pinwi4cWex+FB3Ohvco= github.com/metacubex/sing v0.0.0-20240518125217-e63d65a914d1/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI= github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72 h1:Wr4g1HCb5Z/QIFwFiVNjO2qL+dRu25+Mdn9xtAZZ+ew= diff --git a/clash-meta/transport/tuic/common/congestion.go b/clash-meta/transport/tuic/common/congestion.go index 485e2e6a60..a0e2be68dd 100644 --- a/clash-meta/transport/tuic/common/congestion.go +++ b/clash-meta/transport/tuic/common/congestion.go @@ -22,7 +22,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) { quicConn.SetCongestionControl( congestion.NewCubicSender( congestion.DefaultClock{}, - congestion.GetInitialPacketSize(quicConn.RemoteAddr()), + congestion.GetInitialPacketSize(quicConn), false, ), ) @@ -30,7 +30,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) { quicConn.SetCongestionControl( congestion.NewCubicSender( congestion.DefaultClock{}, - congestion.GetInitialPacketSize(quicConn.RemoteAddr()), + congestion.GetInitialPacketSize(quicConn), true, ), ) @@ -38,7 +38,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) { quicConn.SetCongestionControl( congestion.NewBBRSender( congestion.DefaultClock{}, - congestion.GetInitialPacketSize(quicConn.RemoteAddr()), + congestion.GetInitialPacketSize(quicConn), c.ByteCount(cwnd)*congestion.InitialMaxDatagramSize, congestion.DefaultBBRMaxCongestionWindow*congestion.InitialMaxDatagramSize, ), @@ -49,7 +49,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) { quicConn.SetCongestionControl( congestionv2.NewBbrSender( congestionv2.DefaultClock{}, - congestionv2.GetInitialPacketSize(quicConn.RemoteAddr()), + congestionv2.GetInitialPacketSize(quicConn), c.ByteCount(cwnd), ), ) diff --git a/clash-meta/transport/tuic/congestion/bbr_sender.go b/clash-meta/transport/tuic/congestion/bbr_sender.go index 8c18c616b7..6cea9355fb 100644 --- a/clash-meta/transport/tuic/congestion/bbr_sender.go +++ b/clash-meta/transport/tuic/congestion/bbr_sender.go @@ -5,34 +5,23 @@ package congestion import ( "fmt" "math" - "net" "time" + "github.com/metacubex/quic-go" "github.com/metacubex/quic-go/congestion" "github.com/zhangyunhao116/fastrand" ) const ( // InitialMaxDatagramSize is the default maximum packet size used in QUIC for congestion window computations in bytes. - InitialMaxDatagramSize = 1252 - InitialPacketSizeIPv4 = 1252 - InitialPacketSizeIPv6 = 1232 + InitialMaxDatagramSize = 1280 + InitialPacketSize = 1280 InitialCongestionWindow = 32 DefaultBBRMaxCongestionWindow = 10000 ) -func GetInitialPacketSize(addr net.Addr) congestion.ByteCount { - maxSize := congestion.ByteCount(1200) - // If this is not a UDP address, we don't know anything about the MTU. - // Use the minimum size of an Initial packet as the max packet size. - if udpAddr, ok := addr.(*net.UDPAddr); ok { - if udpAddr.IP.To4() != nil { - maxSize = InitialPacketSizeIPv4 - } else { - maxSize = InitialPacketSizeIPv6 - } - } - return congestion.ByteCount(maxSize) +func GetInitialPacketSize(quicConn quic.Connection) congestion.ByteCount { + return congestion.ByteCount(quicConn.Config().InitialPacketSize) } var ( diff --git a/clash-meta/transport/tuic/congestion/cubic.go b/clash-meta/transport/tuic/congestion/cubic.go index dd491a326a..a9bed43aa1 100644 --- a/clash-meta/transport/tuic/congestion/cubic.go +++ b/clash-meta/transport/tuic/congestion/cubic.go @@ -21,7 +21,7 @@ const ( cubeCongestionWindowScale = 410 cubeFactor congestion.ByteCount = 1 << cubeScale / cubeCongestionWindowScale / maxDatagramSize // TODO: when re-enabling cubic, make sure to use the actual packet size here - maxDatagramSize = congestion.ByteCount(InitialPacketSizeIPv4) + maxDatagramSize = congestion.ByteCount(InitialPacketSize) ) const defaultNumConnections = 1 diff --git a/clash-meta/transport/tuic/congestion_v2/bbr_sender.go b/clash-meta/transport/tuic/congestion_v2/bbr_sender.go index 084f85b12c..54705978cc 100644 --- a/clash-meta/transport/tuic/congestion_v2/bbr_sender.go +++ b/clash-meta/transport/tuic/congestion_v2/bbr_sender.go @@ -4,9 +4,9 @@ package congestion import ( "fmt" - "net" "time" + "github.com/metacubex/quic-go" "github.com/metacubex/quic-go/congestion" "github.com/zhangyunhao116/fastrand" @@ -30,7 +30,7 @@ const ( // Constants based on TCP defaults. // The minimum CWND to ensure delayed acks don't reduce bandwidth measurements. // Does not inflate the pacing rate. - defaultMinimumCongestionWindow = 4 * congestion.ByteCount(congestion.InitialPacketSizeIPv4) + defaultMinimumCongestionWindow = 4 * congestion.ByteCount(congestion.InitialPacketSize) // The gain used for the STARTUP, equal to 2/ln(2). defaultHighGain = 2.885 @@ -931,16 +931,6 @@ func bdpFromRttAndBandwidth(rtt time.Duration, bandwidth Bandwidth) congestion.B return congestion.ByteCount(rtt) * congestion.ByteCount(bandwidth) / congestion.ByteCount(BytesPerSecond) / congestion.ByteCount(time.Second) } -func GetInitialPacketSize(addr net.Addr) congestion.ByteCount { - // If this is not a UDP address, we don't know anything about the MTU. - // Use the minimum size of an Initial packet as the max packet size. - if udpAddr, ok := addr.(*net.UDPAddr); ok { - if udpAddr.IP.To4() != nil { - return congestion.InitialPacketSizeIPv4 - } else { - return congestion.InitialPacketSizeIPv6 - } - } else { - return congestion.MinInitialPacketSize - } +func GetInitialPacketSize(quicConn quic.Connection) congestion.ByteCount { + return congestion.ByteCount(quicConn.Config().InitialPacketSize) } diff --git a/clash-meta/transport/tuic/congestion_v2/pacer.go b/clash-meta/transport/tuic/congestion_v2/pacer.go index ecaf3d1154..174b3dbe3f 100644 --- a/clash-meta/transport/tuic/congestion_v2/pacer.go +++ b/clash-meta/transport/tuic/congestion_v2/pacer.go @@ -21,8 +21,8 @@ type Pacer struct { func NewPacer(getBandwidth func() congestion.ByteCount) *Pacer { p := &Pacer{ - budgetAtLastSent: maxBurstPackets * congestion.InitialPacketSizeIPv4, - maxDatagramSize: congestion.InitialPacketSizeIPv4, + budgetAtLastSent: maxBurstPackets * congestion.InitialPacketSize, + maxDatagramSize: congestion.InitialPacketSize, getBandwidth: getBandwidth, } return p diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index d1cca81981..3907a1c9a6 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -28,17 +28,6 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "ahash" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom 0.2.15", - "once_cell", - "version_check", -] - [[package]] name = "ahash" version = "0.8.11" @@ -200,7 +189,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -395,7 +384,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -430,7 +419,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -752,9 +741,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" dependencies = [ "jobserver", "libc", @@ -865,7 +854,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -887,7 +876,7 @@ dependencies = [ "chrono", "clap", "ctrlc", - "dashmap 5.5.3", + "dashmap", "deelevate", "delay_timer", "dirs 5.0.1", @@ -903,7 +892,7 @@ dependencies = [ "log", "nanoid", "once_cell", - "open 5.1.2", + "open 5.1.3", "parking_lot", "percent-encoding", "port_scanner", @@ -1040,7 +1029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d" dependencies = [ "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1149,9 +1138,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "58ebf8d6963185c7625d2c3c3962d99eb8936637b1427536d21dc36ae402ebad" dependencies = [ "cfg-if", ] @@ -1169,9 +1158,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -1197,9 +1186,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -1241,7 +1230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1251,7 +1240,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1291,7 +1280,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1302,17 +1291,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.63", -] - -[[package]] -name = "dashmap" -version = "4.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" -dependencies = [ - "cfg-if", - "num_cpus", + "syn 2.0.65", ] [[package]] @@ -1350,17 +1329,17 @@ checksum = "83ace6c86376be0b6cdcf3fb41882e81d94b31587573d1cfa9d01cd06bba210d" [[package]] name = "delay_timer" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d70c0d5d2addc05d1e0cf7e60b3a5bf08415f03136a773d7c66b4e4a3b892cef" +checksum = "20eba879b7ee5f1d255d5666e16646fe384f899f71a4c0b4b0644e2e074964fe" dependencies = [ "anyhow", "async-trait", "autocfg", "concat-idents", "cron_clock", - "dashmap 4.0.2", - "event-listener 2.5.3", + "dashmap", + "event-listener 5.3.0", "futures", "log", "lru", @@ -1391,7 +1370,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1402,7 +1381,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1530,7 +1509,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1586,9 +1565,9 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "embed-resource" @@ -1643,7 +1622,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1880,7 +1859,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -2004,7 +1983,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -2442,9 +2421,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.8", -] [[package]] name = "hashbrown" @@ -2452,7 +2428,7 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.11", + "ahash", "allocator-api2", ] @@ -2779,9 +2755,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] @@ -2810,7 +2786,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -2849,7 +2825,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c416c05ba2a10240e022887617af3128fccdbf69713214da0fc81a5690d00df7" dependencies = [ - "ahash 0.8.11", + "ahash", "once_cell", "regex", ] @@ -3093,9 +3069,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libfuzzer-sys" @@ -3168,9 +3144,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litrs" @@ -3188,6 +3164,12 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "lockfree-object-pool" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" + [[package]] name = "log" version = "0.4.21" @@ -3220,11 +3202,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.7.8" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" dependencies = [ - "hashbrown 0.12.3", + "hashbrown 0.14.5", ] [[package]] @@ -3372,9 +3354,9 @@ checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", "simd-adler32", @@ -3599,7 +3581,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -3789,9 +3771,9 @@ dependencies = [ [[package]] name = "open" -version = "5.1.2" +version = "5.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "449f0ff855d85ddbf1edd5b646d65249ead3f5e422aaa86b7d2d0b049b103e32" +checksum = "2eb49fbd5616580e9974662cb96a3463da4476e649a7e4b258df0de065db0657" dependencies = [ "is-wsl", "libc", @@ -3821,7 +3803,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4053,7 +4035,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4191,7 +4173,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4238,7 +4220,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4403,9 +4385,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" dependencies = [ "unicode-ident", ] @@ -4426,7 +4408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" dependencies = [ "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4610,9 +4592,9 @@ checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" [[package]] name = "raw-window-handle" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cc3bcbdb1ddfc11e700e62968e6b4cc9c75bb466464ad28fb61c5b2c964418b" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" [[package]] name = "rayon" @@ -4689,7 +4671,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4903,7 +4885,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml 0.8.26", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4973,7 +4955,7 @@ dependencies = [ "bitflags 2.5.0", "errno", "libc", - "linux-raw-sys 0.4.13", + "linux-raw-sys 0.4.14", "windows-sys 0.52.0", ] @@ -5162,7 +5144,7 @@ checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -5185,7 +5167,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -5236,7 +5218,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -5619,9 +5601,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.63" +version = "2.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" dependencies = [ "proc-macro2", "quote", @@ -6127,7 +6109,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -6240,7 +6222,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -6393,7 +6375,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -6500,12 +6482,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "typed-arena" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" - [[package]] name = "typenum" version = "1.17.0" @@ -6741,7 +6717,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", "wasm-bindgen-shared", ] @@ -6775,7 +6751,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7096,7 +7072,7 @@ checksum = "33082acd404763b315866e14a0d5193f3422c81086657583937a750cdd3ec340" dependencies = [ "cocoa 0.25.0", "objc", - "raw-window-handle 0.6.1", + "raw-window-handle 0.6.2", "windows-sys 0.52.0", "windows-version", ] @@ -7226,7 +7202,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -7237,7 +7213,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -7706,7 +7682,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", - "linux-raw-sys 0.4.13", + "linux-raw-sys 0.4.14", "rustix 0.38.34", ] @@ -7754,9 +7730,9 @@ dependencies = [ [[package]] name = "zbus" -version = "4.2.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5915716dff34abef1351d2b10305b019c8ef33dcf6c72d31a6e227d5d9d7a21" +checksum = "989c3977a7aafa97b12b9a35d21cdcff9b0d2289762b14683f45d66b1ba6c48f" dependencies = [ "async-broadcast", "async-executor", @@ -7792,14 +7768,14 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "4.2.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fceb36d0c1c4a6b98f3ce40f410e64e5a134707ed71892e1b178abc4c695d4" +checksum = "6fe9de53245dcf426b7be226a4217dd5e339080e5d46e64a02d6e5dcbf90fca1" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.65", "zvariant_utils", ] @@ -7831,7 +7807,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -7851,7 +7827,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -7913,14 +7889,16 @@ dependencies = [ [[package]] name = "zopfli" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1f48f3508a3a3f2faee01629564400bc12260f6214a056d06a3aaaa6ef0736" +checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" dependencies = [ + "bumpalo", "crc32fast", + "lockfree-object-pool", "log", + "once_cell", "simd-adler32", - "typed-arena", ] [[package]] @@ -7996,9 +7974,9 @@ dependencies = [ [[package]] name = "zvariant" -version = "4.1.0" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877ef94e5e82b231d2a309c531f191a8152baba8241a7939ee04bd76b0171308" +checksum = "9aa6d31a02fbfb602bfde791de7fedeb9c2c18115b3d00f3a36e489f46ffbbc7" dependencies = [ "endi", "enumflags2", @@ -8009,24 +7987,24 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "4.1.0" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ca98581cc6a8120789d8f1f0997e9053837d6aa5346cbb43454d7121be6e39" +checksum = "642bf1b6b6d527988b3e8193d20969d53700a36eac734d21ae6639db168701c8" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.65", "zvariant_utils", ] [[package]] name = "zvariant_utils" -version = "1.1.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75fa7291bdd68cd13c4f97cc9d78cbf16d96305856dfc7ac942aeff4c2de7d5a" +checksum = "fc242db087efc22bd9ade7aa7809e4ba828132edc312871584a6b4391bdf8786" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.65", ] diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index a467dc7486..5146a6e3e7 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -24,7 +24,7 @@ "@nyanpasu/ui": "workspace:^", "@tauri-apps/api": "1.5.6", "ahooks": "3.7.11", - "axios": "1.6.8", + "axios": "1.7.1", "dayjs": "1.11.11", "framer-motion": "11.2.4", "i18next": "23.11.4", @@ -39,7 +39,6 @@ "react-i18next": "14.1.1", "react-markdown": "9.0.1", "react-router-dom": "6.23.1", - "react-text-transition": "3.1.0", "react-transition-group": "4.4.5", "react-virtuoso": "4.7.10", "swr": "2.2.5", diff --git a/clash-nyanpasu/frontend/nyanpasu/src/pages/proxies.tsx b/clash-nyanpasu/frontend/nyanpasu/src/pages/proxies.tsx index a264124699..f73b2ffd3f 100644 --- a/clash-nyanpasu/frontend/nyanpasu/src/pages/proxies.tsx +++ b/clash-nyanpasu/frontend/nyanpasu/src/pages/proxies.tsx @@ -17,7 +17,7 @@ import { DelayButton, GroupList, NodeList } from "@/components/proxies"; import { Public } from "@mui/icons-material"; import { useAtom } from "jotai"; import { proxyGroupAtom, proxyGroupSortAtom } from "@/store"; -import ReactTextTransition from "react-text-transition"; +import { AnimatePresence, motion } from "framer-motion"; const ContentDisplay = ({ message }: { message: string }) => (
@@ -33,7 +33,19 @@ const ProxyGroupName = memo(function ProxyGroupName({ }: { name: string; }) { - return {name}; + return ( + + + {name} + + + ); }); const SortSelector = memo(function SortSelector() { @@ -158,7 +170,9 @@ export default function ProxyPage() { hasProxies && !getCurrentMode.direct && (
-
{group?.name && }
+
+ {group?.name && } +
diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index f680375b44..d599842e0d 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,7 +2,7 @@ "manifest_version": 1, "latest": { "mihomo": "v1.18.5", - "mihomo_alpha": "alpha-030520e", + "mihomo_alpha": "alpha-c504985", "clash_rs": "v0.1.17", "clash_premium": "2023-09-05-gdcc8d87" }, @@ -36,5 +36,5 @@ "darwin-x64": "clash-darwin-amd64-n{}.gz" } }, - "updated_at": "2024-05-18T22:19:33.070Z" + "updated_at": "2024-05-19T22:20:18.727Z" } diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index ad1dd4cba8..c9c32367a7 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -207,8 +207,8 @@ importers: specifier: 3.7.11 version: 3.7.11(react@19.0.0-beta-04b058868c-20240508) axios: - specifier: 1.6.8 - version: 1.6.8 + specifier: 1.7.1 + version: 1.7.1 dayjs: specifier: 1.11.11 version: 1.11.11 @@ -251,9 +251,6 @@ importers: react-router-dom: specifier: 6.23.1 version: 6.23.1(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508) - react-text-transition: - specifier: 3.1.0 - version: 3.1.0(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508) react-transition-group: specifier: 4.4.5 version: 4.4.5(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508) @@ -1248,30 +1245,6 @@ packages: '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} - '@react-spring/animated@9.7.3': - resolution: {integrity: sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==} - peerDependencies: - react: npm:react@beta - - '@react-spring/core@9.7.3': - resolution: {integrity: sha512-IqFdPVf3ZOC1Cx7+M0cXf4odNLxDC+n7IN3MDcVCTIOSBfqEcBebSv+vlY5AhM0zw05PDbjKrNmBpzv/AqpjnQ==} - peerDependencies: - react: npm:react@beta - - '@react-spring/shared@9.7.3': - resolution: {integrity: sha512-NEopD+9S5xYyQ0pGtioacLhL2luflh6HACSSDUZOwLHoxA5eku1UPuqcJqjwSD6luKjjLfiLOspxo43FUHKKSA==} - peerDependencies: - react: npm:react@beta - - '@react-spring/types@9.7.3': - resolution: {integrity: sha512-Kpx/fQ/ZFX31OtlqVEFfgaD1ACzul4NksrvIgYfIFq9JpDHFwQkMVZ10tbo0FU/grje4rcL4EIrjekl3kYwgWw==} - - '@react-spring/web@9.7.3': - resolution: {integrity: sha512-BXt6BpS9aJL/QdVqEIX9YoUy8CE6TJrU0mNCqSoxdXlIeNcEBWOfIyE6B14ENNsyQKS3wOWkiJfco0tCr/9tUg==} - peerDependencies: - react: npm:react@beta - react-dom: npm:react-dom@beta - '@remix-run/router@1.16.1': resolution: {integrity: sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==} engines: {node: '>=14.0.0'} @@ -1837,8 +1810,8 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axios@1.6.8: - resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==} + axios@1.7.1: + resolution: {integrity: sha512-+LV37nQcd1EpFalkXksWNBiA17NZ5m5/WspmHGmZmdx1qBOg/VNq/c4eRJiA9VQQHBOs+N0ZhhdU10h2TyNK7Q==} babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} @@ -4019,11 +3992,6 @@ packages: peerDependencies: react: npm:react@beta - react-text-transition@3.1.0: - resolution: {integrity: sha512-NtXEVAXvSh78+8JAnrVjpbftzD4kPowacv4GB2Nyq9C/8ko6fSm6M/XvKWQLCaZi68i9F28b++Sp8uVThlzLyg==} - peerDependencies: - react: npm:react@beta - react-transition-group@4.4.5: resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} peerDependencies: @@ -5723,35 +5691,6 @@ snapshots: '@popperjs/core@2.11.8': {} - '@react-spring/animated@9.7.3(react@19.0.0-beta-04b058868c-20240508)': - dependencies: - '@react-spring/shared': 9.7.3(react@19.0.0-beta-04b058868c-20240508) - '@react-spring/types': 9.7.3 - react: 19.0.0-beta-04b058868c-20240508 - - '@react-spring/core@9.7.3(react@19.0.0-beta-04b058868c-20240508)': - dependencies: - '@react-spring/animated': 9.7.3(react@19.0.0-beta-04b058868c-20240508) - '@react-spring/shared': 9.7.3(react@19.0.0-beta-04b058868c-20240508) - '@react-spring/types': 9.7.3 - react: 19.0.0-beta-04b058868c-20240508 - - '@react-spring/shared@9.7.3(react@19.0.0-beta-04b058868c-20240508)': - dependencies: - '@react-spring/types': 9.7.3 - react: 19.0.0-beta-04b058868c-20240508 - - '@react-spring/types@9.7.3': {} - - '@react-spring/web@9.7.3(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508)': - dependencies: - '@react-spring/animated': 9.7.3(react@19.0.0-beta-04b058868c-20240508) - '@react-spring/core': 9.7.3(react@19.0.0-beta-04b058868c-20240508) - '@react-spring/shared': 9.7.3(react@19.0.0-beta-04b058868c-20240508) - '@react-spring/types': 9.7.3 - react: 19.0.0-beta-04b058868c-20240508 - react-dom: 19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508) - '@remix-run/router@1.16.1': {} '@rollup/pluginutils@5.1.0(rollup@4.17.2)': @@ -6332,7 +6271,7 @@ snapshots: dependencies: possible-typed-array-names: 1.0.0 - axios@1.6.8: + axios@1.7.1: dependencies: follow-redirects: 1.15.6 form-data: 4.0.0 @@ -8756,13 +8695,6 @@ snapshots: '@remix-run/router': 1.16.1 react: 19.0.0-beta-04b058868c-20240508 - react-text-transition@3.1.0(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508): - dependencies: - '@react-spring/web': 9.7.3(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508) - react: 19.0.0-beta-04b058868c-20240508 - transitivePeerDependencies: - - react-dom - react-transition-group@4.4.5(react-dom@19.0.0-beta-04b058868c-20240508(react@19.0.0-beta-04b058868c-20240508))(react@19.0.0-beta-04b058868c-20240508): dependencies: '@babel/runtime': 7.24.5 diff --git a/clash-verge-rev/src/components/connection/connection-detail.tsx b/clash-verge-rev/src/components/connection/connection-detail.tsx index 1ddfc2c7da..055fb712d7 100644 --- a/clash-verge-rev/src/components/connection/connection-detail.tsx +++ b/clash-verge-rev/src/components/connection/connection-detail.tsx @@ -54,29 +54,32 @@ const InnerConnectionDetail = ({ data, onClose }: InnerProps) => { : `${metadata.destinationIP}:${metadata.destinationPort}`; const information = [ - { label: "Host", value: host }, - { label: "Download", value: parseTraffic(data.download).join(" ") }, - { label: "Upload", value: parseTraffic(data.upload).join(" ") }, + { label: t("Host"), value: host }, + { label: t("Downloaded"), value: parseTraffic(data.download).join(" ") }, + { label: t("Uploaded"), value: parseTraffic(data.upload).join(" ") }, { - label: "DL Speed", + label: t("DL Speed"), value: parseTraffic(data.curDownload ?? -1).join(" ") + "/s", }, { - label: "UL Speed", + label: t("UL Speed"), value: parseTraffic(data.curUpload ?? -1).join(" ") + "/s", }, - { label: "Chains", value: chains }, - { label: "Rule", value: rule }, + { label: t("Chains"), value: chains }, + { label: t("Rule"), value: rule }, { - label: "Process", + label: t("Process"), value: `${metadata.process}${ metadata.processPath ? `(${metadata.processPath})` : "" }`, }, - { label: "Time", value: dayjs(data.start).fromNow() }, - { label: "Source", value: `${metadata.sourceIP}:${metadata.sourcePort}` }, - { label: "Destination IP", value: metadata.destinationIP }, - { label: "Type", value: `${metadata.type}(${metadata.network})` }, + { label: t("Time"), value: dayjs(data.start).fromNow() }, + { + label: t("Source"), + value: `${metadata.sourceIP}:${metadata.sourcePort}`, + }, + { label: t("Destination IP"), value: metadata.destinationIP }, + { label: t("Type"), value: `${metadata.type}(${metadata.network})` }, ]; const onDelete = useLockFn(async () => deleteConnection(data.id)); @@ -92,13 +95,13 @@ const InnerConnectionDetail = ({ data, onClose }: InnerProps) => { diff --git a/clash-verge-rev/src/components/connection/connection-table.tsx b/clash-verge-rev/src/components/connection/connection-table.tsx index 036d844c7b..be1461ef3b 100644 --- a/clash-verge-rev/src/components/connection/connection-table.tsx +++ b/clash-verge-rev/src/components/connection/connection-table.tsx @@ -7,6 +7,7 @@ import { } from "@mui/x-data-grid"; import { truncateStr } from "@/utils/truncate-str"; import parseTraffic from "@/utils/parse-traffic"; +import { t } from "i18next"; interface Props { connections: IConnectionsItem[]; @@ -21,10 +22,10 @@ export const ConnectionTable = (props: Props) => { >({}); const columns: GridColDef[] = [ - { field: "host", headerName: "Host", flex: 220, minWidth: 220 }, + { field: "host", headerName: t("Host"), flex: 220, minWidth: 220 }, { field: "download", - headerName: "Download", + headerName: t("Downloaded"), width: 88, align: "right", headerAlign: "right", @@ -33,7 +34,7 @@ export const ConnectionTable = (props: Props) => { }, { field: "upload", - headerName: "Upload", + headerName: t("Uploaded"), width: 88, align: "right", headerAlign: "right", @@ -42,7 +43,7 @@ export const ConnectionTable = (props: Props) => { }, { field: "dlSpeed", - headerName: "DL Speed", + headerName: t("DL Speed"), width: 88, align: "right", headerAlign: "right", @@ -51,19 +52,19 @@ export const ConnectionTable = (props: Props) => { }, { field: "ulSpeed", - headerName: "UL Speed", + headerName: t("UL Speed"), width: 88, align: "right", headerAlign: "right", valueFormatter: (params: GridValueFormatterParams) => parseTraffic(params.value).join(" ") + "/s", }, - { field: "chains", headerName: "Chains", flex: 360, minWidth: 360 }, - { field: "rule", headerName: "Rule", flex: 300, minWidth: 250 }, - { field: "process", headerName: "Process", flex: 240, minWidth: 120 }, + { field: "chains", headerName: t("Chains"), flex: 360, minWidth: 360 }, + { field: "rule", headerName: t("Rule"), flex: 300, minWidth: 250 }, + { field: "process", headerName: t("Process"), flex: 240, minWidth: 120 }, { field: "time", - headerName: "Time", + headerName: t("Time"), flex: 120, minWidth: 100, align: "right", @@ -74,14 +75,14 @@ export const ConnectionTable = (props: Props) => { valueFormatter: (params: GridValueFormatterParams) => dayjs(params.value).fromNow(), }, - { field: "source", headerName: "Source", flex: 200, minWidth: 130 }, + { field: "source", headerName: t("Source"), flex: 200, minWidth: 130 }, { field: "destinationIP", - headerName: "Destination IP", + headerName: t("Destination IP"), flex: 200, minWidth: 130, }, - { field: "type", headerName: "Type", flex: 160, minWidth: 100 }, + { field: "type", headerName: t("Type"), flex: 160, minWidth: 100 }, ]; const connRows = useMemo(() => { diff --git a/clash-verge-rev/src/components/log/log-item.tsx b/clash-verge-rev/src/components/log/log-item.tsx index 1aa0804058..012eb2e32c 100644 --- a/clash-verge-rev/src/components/log/log-item.tsx +++ b/clash-verge-rev/src/components/log/log-item.tsx @@ -30,6 +30,7 @@ const Item = styled(Box)(({ theme: { palette, typography } }) => ({ }, "& .data": { color: palette.text.primary, + overflowWrap: "anywhere", }, })); diff --git a/clash-verge-rev/src/components/setting/mods/hotkey-viewer.tsx b/clash-verge-rev/src/components/setting/mods/hotkey-viewer.tsx index edca6c4958..27e2ac4b68 100644 --- a/clash-verge-rev/src/components/setting/mods/hotkey-viewer.tsx +++ b/clash-verge-rev/src/components/setting/mods/hotkey-viewer.tsx @@ -79,7 +79,7 @@ export const HotkeyViewer = forwardRef((props, ref) => { return ( ((props, ref) => { + + @@ -155,9 +157,17 @@ export const SysproxyViewer = forwardRef((props, ref) => { {t("Bypass")} - - {sysproxy?.bypass || "-"} - + + + diff --git a/clash-verge-rev/src/components/setting/mods/theme-viewer.tsx b/clash-verge-rev/src/components/setting/mods/theme-viewer.tsx index daa7e53393..7aa8424a29 100644 --- a/clash-verge-rev/src/components/setting/mods/theme-viewer.tsx +++ b/clash-verge-rev/src/components/setting/mods/theme-viewer.tsx @@ -1,4 +1,4 @@ -import { forwardRef, useImperativeHandle, useRef, useState } from "react"; +import { forwardRef, useImperativeHandle, useState } from "react"; import { useLockFn } from "ahooks"; import { useTranslation } from "react-i18next"; import { diff --git a/clash-verge-rev/src/components/setting/setting-system.tsx b/clash-verge-rev/src/components/setting/setting-system.tsx index 44b67f8fba..a742d42ea6 100644 --- a/clash-verge-rev/src/components/setting/setting-system.tsx +++ b/clash-verge-rev/src/components/setting/setting-system.tsx @@ -11,7 +11,6 @@ import { GuardState } from "./mods/guard-state"; import { ServiceViewer } from "./mods/service-viewer"; import { SysproxyViewer } from "./mods/sysproxy-viewer"; import { TunViewer } from "./mods/tun-viewer"; -import getSystem from "@/utils/get-system"; interface Props { onError?: (err: Error) => void; diff --git a/clash-verge-rev/src/locales/en.json b/clash-verge-rev/src/locales/en.json index 17b5c4f524..0aa249d63b 100644 --- a/clash-verge-rev/src/locales/en.json +++ b/clash-verge-rev/src/locales/en.json @@ -25,6 +25,7 @@ "Test URL": "Test URL", "Test All": "Test All", + "Paste": "Paste", "Profiles": "Profiles", "Profile URL": "Profile URL", "Import": "Import", @@ -70,6 +71,19 @@ "Update All": "Update All", "Update At": "Update At", + "Host": "Host", + "Downloaded": "Downloaded", + "Uploaded": "Uploaded", + "DL Speed": "DL Speed", + "UL Speed": "UL Speed", + "Chains": "Chains", + "Rule": "Rule", + "Process": "Process", + "Time": "Time", + "Source": "Source", + "Destination IP": "Destination IP", + "Close Connection": "Close Connection", + "Type": "Type", "Name": "Name", "Descriptions": "Descriptions", diff --git a/clash-verge-rev/src/locales/ru.json b/clash-verge-rev/src/locales/ru.json index fafd7c840e..e4d7636acc 100644 --- a/clash-verge-rev/src/locales/ru.json +++ b/clash-verge-rev/src/locales/ru.json @@ -25,6 +25,7 @@ "Test URL": "Тестовый URL", "Test All": "Тест Все", + "Paste": "Вставить", "Profiles": "Профили", "Profile URL": "URL профиля", "Import": "Импорт", @@ -70,6 +71,19 @@ "Update All": "Обновить все", "Update At": "Обновлено в", + "Host": "Хост", + "Downloaded": "Скачано", + "Uploaded": "Загружено", + "DL Speed": "Скорость загрузки", + "UL Speed": "Скорость выгрузки", + "Chains": "Цепочки", + "Rule": "Правило", + "Process": "Процесс", + "Time": "Время подключения", + "Source": "Исходный адрес", + "Destination IP": "IP-адрес назначения", + "Close Connection": "Закрыть соединение", + "Type": "Тип", "Name": "Название", "Descriptions": "Описания", diff --git a/clash-verge-rev/src/locales/zh.json b/clash-verge-rev/src/locales/zh.json index 19a7e7b046..22cec44cb1 100644 --- a/clash-verge-rev/src/locales/zh.json +++ b/clash-verge-rev/src/locales/zh.json @@ -25,6 +25,7 @@ "Test URL": "测试地址", "Test All": "测试全部", + "Paste": "粘贴", "Profiles": "订阅", "Profile URL": "订阅文件链接", "Import": "导入", @@ -70,6 +71,19 @@ "Update All": "更新全部", "Update At": "更新于", + "Host": "主机", + "Downloaded": "下载量", + "Uploaded": "上传量", + "DL Speed": "下载速度", + "UL Speed": "上传速度", + "Chains": "链路", + "Rule": "规则", + "Process": "进程", + "Time": "连接时间", + "Source": "源地址", + "Destination IP": "目标地址", + "Close Connection": "关闭连接", + "Type": "类型", "Name": "名称", "Descriptions": "描述", diff --git a/clash-verge-rev/src/pages/connections.tsx b/clash-verge-rev/src/pages/connections.tsx index 87b9ec7352..96c9a03824 100644 --- a/clash-verge-rev/src/pages/connections.tsx +++ b/clash-verge-rev/src/pages/connections.tsx @@ -134,8 +134,12 @@ const ConnectionsPage = () => { contentStyle={{ height: "100%" }} header={ - Download: {parseTraffic(download)} - Upload: {parseTraffic(upload)} + + {t("Downloaded")}: {parseTraffic(download)} + + + {t("Uploaded")}: {parseTraffic(upload)} + cloned && atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1, &shinfo->dataref)) @@ -629,7 +629,7 @@ } /* -@@ -1002,6 +1022,7 @@ static struct sk_buff *__skb_clone(struc +@@ -1003,6 +1023,7 @@ static struct sk_buff *__skb_clone(struc n->nohdr = 0; n->peeked = 0; C(pfmemalloc); @@ -637,7 +637,7 @@ n->destructor = NULL; C(tail); C(end); -@@ -3420,7 +3441,7 @@ int skb_shift(struct sk_buff *tgt, struc +@@ -3432,7 +3453,7 @@ int skb_shift(struct sk_buff *tgt, struc fragto = &skb_shinfo(tgt)->frags[merge]; skb_frag_size_add(fragto, skb_frag_size(fragfrom)); @@ -646,7 +646,7 @@ } /* Reposition in the original skb */ -@@ -5204,6 +5225,20 @@ bool skb_try_coalesce(struct sk_buff *to +@@ -5216,6 +5237,20 @@ bool skb_try_coalesce(struct sk_buff *to if (skb_cloned(to)) return false; @@ -687,7 +687,7 @@ #ifdef CONFIG_SKB_EXTENSIONS __u8 active_extensions; #endif -@@ -3030,9 +3032,15 @@ static inline void skb_frag_ref(struct s +@@ -3045,9 +3047,15 @@ static inline void skb_frag_ref(struct s * * Releases a reference on the paged fragment @frag. */ @@ -705,7 +705,7 @@ } /** -@@ -3044,7 +3052,7 @@ static inline void __skb_frag_unref(skb_ +@@ -3059,7 +3067,7 @@ static inline void __skb_frag_unref(skb_ */ static inline void skb_frag_unref(struct sk_buff *skb, int f) { @@ -714,7 +714,7 @@ } /** -@@ -4643,5 +4651,12 @@ static inline u64 skb_get_kcov_handle(st +@@ -4658,5 +4666,12 @@ static inline u64 skb_get_kcov_handle(st #endif } diff --git a/lede/target/linux/generic/backport-5.10/633-v6.3-skbuff-Fix-a-race-between-coalescing-and-releasing-S.patch b/lede/target/linux/generic/backport-5.10/633-v6.3-skbuff-Fix-a-race-between-coalescing-and-releasing-S.patch index a461734b6a..57230fcd17 100644 --- a/lede/target/linux/generic/backport-5.10/633-v6.3-skbuff-Fix-a-race-between-coalescing-and-releasing-S.patch +++ b/lede/target/linux/generic/backport-5.10/633-v6.3-skbuff-Fix-a-race-between-coalescing-and-releasing-S.patch @@ -56,7 +56,7 @@ Signed-off-by: Jakub Kicinski --- a/net/core/skbuff.c +++ b/net/core/skbuff.c -@@ -5225,18 +5225,18 @@ bool skb_try_coalesce(struct sk_buff *to +@@ -5237,18 +5237,18 @@ bool skb_try_coalesce(struct sk_buff *to if (skb_cloned(to)) return false; diff --git a/lede/target/linux/generic/backport-5.4/746-v5.5-net-dsa-mv88e6xxx-Split-monitor-port-configuration.patch b/lede/target/linux/generic/backport-5.4/746-v5.5-net-dsa-mv88e6xxx-Split-monitor-port-configuration.patch index 86885c2b26..b5c0ac5051 100644 --- a/lede/target/linux/generic/backport-5.4/746-v5.5-net-dsa-mv88e6xxx-Split-monitor-port-configuration.patch +++ b/lede/target/linux/generic/backport-5.4/746-v5.5-net-dsa-mv88e6xxx-Split-monitor-port-configuration.patch @@ -49,7 +49,7 @@ Signed-off-by: David S. Miller enum mv88e6xxx_frame_mode { MV88E6XXX_FRAME_MODE_NORMAL, MV88E6XXX_FRAME_MODE_DSA, -@@ -464,7 +469,9 @@ struct mv88e6xxx_ops { +@@ -465,7 +470,9 @@ struct mv88e6xxx_ops { int (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port, uint64_t *data); int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port); diff --git a/lede/target/linux/generic/backport-5.4/747-v5.5-net-dsa-mv88e6xxx-Add-support-for-port-mirroring.patch b/lede/target/linux/generic/backport-5.4/747-v5.5-net-dsa-mv88e6xxx-Add-support-for-port-mirroring.patch index 0e69fb292f..3ac7a4f0fc 100644 --- a/lede/target/linux/generic/backport-5.4/747-v5.5-net-dsa-mv88e6xxx-Add-support-for-port-mirroring.patch +++ b/lede/target/linux/generic/backport-5.4/747-v5.5-net-dsa-mv88e6xxx-Add-support-for-port-mirroring.patch @@ -25,7 +25,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -4944,6 +4944,80 @@ static int mv88e6xxx_port_mdb_del(struct +@@ -4969,6 +4969,80 @@ static int mv88e6xxx_port_mdb_del(struct return err; } @@ -106,7 +106,7 @@ Signed-off-by: David S. Miller static int mv88e6xxx_port_egress_floods(struct dsa_switch *ds, int port, bool unicast, bool multicast) { -@@ -4998,6 +5072,8 @@ static const struct dsa_switch_ops mv88e +@@ -5023,6 +5097,8 @@ static const struct dsa_switch_ops mv88e .port_mdb_prepare = mv88e6xxx_port_mdb_prepare, .port_mdb_add = mv88e6xxx_port_mdb_add, .port_mdb_del = mv88e6xxx_port_mdb_del, @@ -117,7 +117,7 @@ Signed-off-by: David S. Miller .port_hwtstamp_set = mv88e6xxx_port_hwtstamp_set, --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h -@@ -232,6 +232,8 @@ struct mv88e6xxx_port { +@@ -233,6 +233,8 @@ struct mv88e6xxx_port { u64 vtu_member_violation; u64 vtu_miss_violation; u8 cmode; @@ -126,7 +126,7 @@ Signed-off-by: David S. Miller unsigned int serdes_irq; }; -@@ -315,6 +317,10 @@ struct mv88e6xxx_chip { +@@ -316,6 +318,10 @@ struct mv88e6xxx_chip { u16 evcap_config; u16 enable_count; diff --git a/lede/target/linux/generic/backport-5.4/748-v5.5-net-dsa-mv88e6xxx-fix-broken-if-statement-because-of.patch b/lede/target/linux/generic/backport-5.4/748-v5.5-net-dsa-mv88e6xxx-fix-broken-if-statement-because-of.patch index 017a68958c..5d68ba579e 100644 --- a/lede/target/linux/generic/backport-5.4/748-v5.5-net-dsa-mv88e6xxx-fix-broken-if-statement-because-of.patch +++ b/lede/target/linux/generic/backport-5.4/748-v5.5-net-dsa-mv88e6xxx-fix-broken-if-statement-because-of.patch @@ -19,7 +19,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -5011,7 +5011,7 @@ static void mv88e6xxx_port_mirror_del(st +@@ -5036,7 +5036,7 @@ static void mv88e6xxx_port_mirror_del(st if (chip->info->ops->set_egress_port(chip, direction, dsa_upstream_port(ds, diff --git a/lede/target/linux/generic/backport-5.4/782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch b/lede/target/linux/generic/backport-5.4/782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch index 5027a8904e..aa0c251b13 100644 --- a/lede/target/linux/generic/backport-5.4/782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch +++ b/lede/target/linux/generic/backport-5.4/782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch @@ -1833,7 +1833,7 @@ Signed-off-by: David S. Miller } --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c -@@ -3459,10 +3459,11 @@ static int bcmgenet_probe(struct platfor +@@ -3467,10 +3467,11 @@ static int bcmgenet_probe(struct platfor const struct of_device_id *of_id = NULL; struct bcmgenet_priv *priv; struct net_device *dev; @@ -1846,7 +1846,7 @@ Signed-off-by: David S. Miller /* Up to GENET_MAX_MQ_CNT + 1 TX queues and RX queues */ dev = alloc_etherdev_mqs(sizeof(*priv), GENET_MAX_MQ_CNT + 1, -@@ -3489,14 +3490,15 @@ static int bcmgenet_probe(struct platfor +@@ -3497,14 +3498,15 @@ static int bcmgenet_probe(struct platfor } if (dn) { @@ -1865,7 +1865,7 @@ Signed-off-by: David S. Miller } priv->base = devm_platform_ioremap_resource(pdev, 0); -@@ -3509,7 +3511,6 @@ static int bcmgenet_probe(struct platfor +@@ -3517,7 +3519,6 @@ static int bcmgenet_probe(struct platfor SET_NETDEV_DEV(dev, &pdev->dev); dev_set_drvdata(&pdev->dev, dev); diff --git a/lede/target/linux/generic/hack-5.10/721-net-add-packet-mangeling.patch b/lede/target/linux/generic/hack-5.10/721-net-add-packet-mangeling.patch index 8f6702e433..cea9bb000b 100644 --- a/lede/target/linux/generic/hack-5.10/721-net-add-packet-mangeling.patch +++ b/lede/target/linux/generic/hack-5.10/721-net-add-packet-mangeling.patch @@ -60,7 +60,7 @@ Signed-off-by: Felix Fietkau */ --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -2728,6 +2728,10 @@ static inline int pskb_trim(struct sk_bu +@@ -2743,6 +2743,10 @@ static inline int pskb_trim(struct sk_bu return (len < skb->len) ? __pskb_trim(skb, len) : 0; } @@ -71,7 +71,7 @@ Signed-off-by: Felix Fietkau /** * pskb_trim_unique - remove end from a paged unique (not cloned) buffer * @skb: buffer to alter -@@ -2859,16 +2863,6 @@ static inline struct sk_buff *dev_alloc_ +@@ -2874,16 +2878,6 @@ static inline struct sk_buff *dev_alloc_ } @@ -119,15 +119,15 @@ Signed-off-by: Felix Fietkau trace_net_dev_start_xmit(skb, dev); --- a/net/core/skbuff.c +++ b/net/core/skbuff.c -@@ -60,6 +60,7 @@ - #include +@@ -61,6 +61,7 @@ #include #include + #include +#include #include #include -@@ -553,6 +554,22 @@ skb_fail: +@@ -554,6 +555,22 @@ skb_fail: } EXPORT_SYMBOL(__napi_alloc_skb); diff --git a/lede/target/linux/generic/hack-5.10/953-net-patch-linux-kernel-to-support-shortcut-fe.patch b/lede/target/linux/generic/hack-5.10/953-net-patch-linux-kernel-to-support-shortcut-fe.patch index 11a15a6fe4..2a76af1065 100644 --- a/lede/target/linux/generic/hack-5.10/953-net-patch-linux-kernel-to-support-shortcut-fe.patch +++ b/lede/target/linux/generic/hack-5.10/953-net-patch-linux-kernel-to-support-shortcut-fe.patch @@ -12,9 +12,9 @@ struct list_head *br_ip_list); --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -866,6 +866,10 @@ struct sk_buff { +@@ -865,6 +865,10 @@ struct sk_buff { + #endif __u8 scm_io_uring:1; - __u8 gro_skip:1; +#ifdef CONFIG_SHORTCUT_FE + __u8 fast_forwarded:1; diff --git a/lede/target/linux/generic/hack-5.4/721-phy_packets.patch b/lede/target/linux/generic/hack-5.4/721-phy_packets.patch index 89d5b965a2..2336bcdee4 100644 --- a/lede/target/linux/generic/hack-5.4/721-phy_packets.patch +++ b/lede/target/linux/generic/hack-5.4/721-phy_packets.patch @@ -56,7 +56,7 @@ Signed-off-by: Felix Fietkau */ --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -2695,6 +2695,10 @@ static inline int pskb_trim(struct sk_bu +@@ -2710,6 +2710,10 @@ static inline int pskb_trim(struct sk_bu return (len < skb->len) ? __pskb_trim(skb, len) : 0; } @@ -67,7 +67,7 @@ Signed-off-by: Felix Fietkau /** * pskb_trim_unique - remove end from a paged unique (not cloned) buffer * @skb: buffer to alter -@@ -2826,16 +2830,6 @@ static inline struct sk_buff *dev_alloc_ +@@ -2841,16 +2845,6 @@ static inline struct sk_buff *dev_alloc_ } diff --git a/lede/target/linux/generic/pending-5.10/655-increase_skb_pad.patch b/lede/target/linux/generic/pending-5.10/655-increase_skb_pad.patch index dafafad588..c94563a6ae 100644 --- a/lede/target/linux/generic/pending-5.10/655-increase_skb_pad.patch +++ b/lede/target/linux/generic/pending-5.10/655-increase_skb_pad.patch @@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -2694,7 +2694,7 @@ static inline int pskb_network_may_pull( +@@ -2709,7 +2709,7 @@ static inline int pskb_network_may_pull( * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8) */ #ifndef NET_SKB_PAD diff --git a/lede/target/linux/generic/pending-5.10/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/lede/target/linux/generic/pending-5.10/680-NET-skip-GRO-for-foreign-MAC-addresses.patch index 78c6d2a545..8b06c2ca2b 100644 --- a/lede/target/linux/generic/pending-5.10/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +++ b/lede/target/linux/generic/pending-5.10/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -1995,6 +1995,8 @@ struct net_device { +@@ -2061,6 +2061,8 @@ struct net_device { struct netdev_hw_addr_list mc; struct netdev_hw_addr_list dev_addrs; @@ -22,7 +22,7 @@ Signed-off-by: Felix Fietkau #endif --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -831,6 +831,7 @@ struct sk_buff { +@@ -868,6 +868,7 @@ struct sk_buff { #ifdef CONFIG_NET_SCHED __u16 tc_index; /* traffic control index */ #endif @@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau __wsum csum; --- a/net/core/dev.c +++ b/net/core/dev.c -@@ -5516,6 +5516,9 @@ static enum gro_result dev_gro_receive(s +@@ -6081,6 +6081,9 @@ static enum gro_result dev_gro_receive(s int same_flow; int grow; @@ -42,7 +42,7 @@ Signed-off-by: Felix Fietkau if (netif_elide_gro(skb->dev)) goto normal; -@@ -7318,6 +7321,48 @@ static void __netdev_adjacent_dev_unlink +@@ -8060,6 +8063,48 @@ static void __netdev_adjacent_dev_unlink &upper_dev->adj_list.lower); } @@ -91,7 +91,7 @@ Signed-off-by: Felix Fietkau static int __netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev, bool master, void *upper_priv, void *upper_info, -@@ -7368,6 +7413,7 @@ static int __netdev_upper_dev_link(struc +@@ -8111,6 +8156,7 @@ static int __netdev_upper_dev_link(struc if (ret) return ret; @@ -99,7 +99,7 @@ Signed-off-by: Felix Fietkau ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); ret = notifier_to_errno(ret); -@@ -7461,6 +7507,7 @@ void netdev_upper_dev_unlink(struct net_ +@@ -8207,6 +8253,7 @@ static void __netdev_upper_dev_unlink(st __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); @@ -107,7 +107,7 @@ Signed-off-by: Felix Fietkau call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, &changeupper_info.info); -@@ -8191,6 +8238,7 @@ int dev_set_mac_address(struct net_devic +@@ -8993,6 +9040,7 @@ int dev_set_mac_address(struct net_devic if (err) return err; dev->addr_assign_type = NET_ADDR_SET; @@ -136,7 +136,7 @@ Signed-off-by: Felix Fietkau /** * eth_type_trans - determine the packet's protocol ID. * @skb: received socket data -@@ -184,6 +184,9 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) +@@ -166,6 +178,9 @@ __be16 eth_type_trans(struct sk_buff *sk eth_skb_pkt_type(skb, dev); diff --git a/lede/target/linux/generic/pending-5.10/750-skb-Do-mix-page-pool-and-page-referenced-frags-in-GR.patch b/lede/target/linux/generic/pending-5.10/750-skb-Do-mix-page-pool-and-page-referenced-frags-in-GR.patch index 278a0b7e86..d64e334afd 100644 --- a/lede/target/linux/generic/pending-5.10/750-skb-Do-mix-page-pool-and-page-referenced-frags-in-GR.patch +++ b/lede/target/linux/generic/pending-5.10/750-skb-Do-mix-page-pool-and-page-referenced-frags-in-GR.patch @@ -17,7 +17,7 @@ Signed-off-by: Alexander Duyck --- a/net/core/skbuff.c +++ b/net/core/skbuff.c -@@ -4176,6 +4176,15 @@ int skb_gro_receive(struct sk_buff *p, s +@@ -4188,6 +4188,15 @@ int skb_gro_receive(struct sk_buff *p, s if (unlikely(p->len + len >= 65536 || NAPI_GRO_CB(skb)->flush)) return -E2BIG; diff --git a/lede/target/linux/generic/pending-5.4/655-increase_skb_pad.patch b/lede/target/linux/generic/pending-5.4/655-increase_skb_pad.patch index 3ca190f0aa..ff39ddb8b3 100644 --- a/lede/target/linux/generic/pending-5.4/655-increase_skb_pad.patch +++ b/lede/target/linux/generic/pending-5.4/655-increase_skb_pad.patch @@ -9,7 +9,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h -@@ -2661,7 +2661,7 @@ static inline int pskb_network_may_pull( +@@ -2676,7 +2676,7 @@ static inline int pskb_network_may_pull( * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8) */ #ifndef NET_SKB_PAD diff --git a/lede/target/linux/generic/pending-5.4/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/lede/target/linux/generic/pending-5.4/680-NET-skip-GRO-for-foreign-MAC-addresses.patch index 78c6d2a545..6fe3df256a 100644 --- a/lede/target/linux/generic/pending-5.4/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +++ b/lede/target/linux/generic/pending-5.4/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -1995,6 +1995,8 @@ struct net_device { +@@ -1999,6 +1999,8 @@ struct net_device { struct netdev_hw_addr_list mc; struct netdev_hw_addr_list dev_addrs; @@ -136,7 +136,7 @@ Signed-off-by: Felix Fietkau /** * eth_type_trans - determine the packet's protocol ID. * @skb: received socket data -@@ -184,6 +184,9 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) +@@ -166,6 +178,9 @@ __be16 eth_type_trans(struct sk_buff *sk eth_skb_pkt_type(skb, dev); diff --git a/lede/target/linux/generic/pending-5.4/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch b/lede/target/linux/generic/pending-5.4/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch index 4d6e0f99db..93c414b632 100644 --- a/lede/target/linux/generic/pending-5.4/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch +++ b/lede/target/linux/generic/pending-5.4/768-net-dsa-mv88e6xxx-Request-assisted-learning-on-CPU-port.patch @@ -17,7 +17,7 @@ Signed-off-by: Tobias Waldekranz --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c -@@ -5098,6 +5098,7 @@ static int mv88e6xxx_register_switch(str +@@ -5123,6 +5123,7 @@ static int mv88e6xxx_register_switch(str ds->ops = &mv88e6xxx_switch_ops; ds->ageing_time_min = chip->info->age_time_coeff; ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX; diff --git a/lede/target/linux/ramips/patches-5.10/902-mtkhnat-fix-pskb-expand-head-limitation.patch b/lede/target/linux/ramips/patches-5.10/902-mtkhnat-fix-pskb-expand-head-limitation.patch index 9bd7432de9..53b3b1b5bd 100644 --- a/lede/target/linux/ramips/patches-5.10/902-mtkhnat-fix-pskb-expand-head-limitation.patch +++ b/lede/target/linux/ramips/patches-5.10/902-mtkhnat-fix-pskb-expand-head-limitation.patch @@ -1,6 +1,6 @@ --- a/net/core/skbuff.c +++ b/net/core/skbuff.c -@@ -70,6 +70,7 @@ +@@ -71,6 +71,7 @@ #include #include #include @@ -8,7 +8,7 @@ #include #include -@@ -1686,6 +1687,9 @@ int pskb_expand_head(struct sk_buff *skb +@@ -1693,6 +1694,9 @@ int pskb_expand_head(struct sk_buff *skb skb_shinfo(skb), offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags])); diff --git a/mihomo/.github/workflows/build.yml b/mihomo/.github/workflows/build.yml index 84536a547b..42023755e1 100644 --- a/mihomo/.github/workflows/build.yml +++ b/mihomo/.github/workflows/build.yml @@ -18,7 +18,7 @@ on: branches: - Alpha concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true env: @@ -270,7 +270,7 @@ jobs: - name: Archive production artifacts uses: actions/upload-artifact@v4 with: - name: ${{ matrix.jobs.goos }}-${{ matrix.jobs.output }} + name: "${{ matrix.jobs.goos }}-${{ matrix.jobs.output }}" path: | mihomo*.gz mihomo*.deb @@ -415,35 +415,35 @@ jobs: uses: docker/setup-buildx-action@v3 with: version: latest - - - name: Set Docker tags and labels based on trigger - id: set-meta - run: | - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - echo "tags=${{ github.event.inputs.version }}" >> $GITHUB_ENV - echo "labels=org.opencontainers.image.version=${{ github.event.inputs.version }}" >> $GITHUB_ENV - else - echo "tags=${{ steps.meta.outputs.tags }}" >> $GITHUB_ENV - echo "labels=${{ steps.meta.outputs.labels }}" >> $GITHUB_ENV - fi - - + # Extract metadata (tags, labels) for Docker # https://github.com/docker/metadata-action - name: Extract Docker metadata - id: meta + if: ${{ github.event_name != 'workflow_dispatch' }} + id: meta_alpha uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ github.repository }} - tags: ${{ env.tags }} - labels: ${{ env.labels }} - - + images: '${{ env.REGISTRY }}/${{ github.repository }}' + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' }} + id: meta_release + uses: docker/metadata-action@v5 + with: + images: '${{ env.REGISTRY }}/${{ github.repository }}' + tags: | + ${{ github.event.inputs.version }} + flavor: | + latest=true + labels: org.opencontainers.image.version=${{ github.event.inputs.version }} + - name: Show files run: | ls . ls bin/ - + - name: login to docker REGISTRY uses: docker/login-action@v3 with: @@ -454,7 +454,7 @@ jobs: # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image - id: build-and-push + if: ${{ github.event_name != 'workflow_dispatch' }} uses: docker/build-push-action@v5 with: context: . @@ -465,5 +465,20 @@ jobs: linux/amd64 linux/arm64 linux/arm/v7 - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file + tags: ${{ steps.meta_alpha.outputs.tags }} + labels: ${{ steps.meta_alpha.outputs.labels }} + + - name: Build and push Docker image + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' }} + uses: docker/build-push-action@v5 + with: + context: . + file: ./Dockerfile + push: ${{ github.event_name != 'pull_request' }} + platforms: | + linux/386 + linux/amd64 + linux/arm64 + linux/arm/v7 + tags: ${{ steps.meta_release.outputs.tags }} + labels: ${{ steps.meta_release.outputs.labels }} \ No newline at end of file diff --git a/mihomo/go.mod b/mihomo/go.mod index d9ed12289b..601929c189 100644 --- a/mihomo/go.mod +++ b/mihomo/go.mod @@ -19,7 +19,7 @@ require ( github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 github.com/mdlayher/netlink v1.7.2 github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 - github.com/metacubex/quic-go v0.43.2-0.20240518033621-2c3d14c6b38e + github.com/metacubex/quic-go v0.44.1-0.20240520163451-20b689a59136 github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72 github.com/metacubex/sing-shadowsocks v0.2.6 github.com/metacubex/sing-shadowsocks2 v0.2.0 diff --git a/mihomo/go.sum b/mihomo/go.sum index fb14d71525..091f6cf126 100644 --- a/mihomo/go.sum +++ b/mihomo/go.sum @@ -104,8 +104,8 @@ github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvO github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88= github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec h1:HxreOiFTUrJXJautEo8rnE1uKTVGY8wtZepY1Tii/Nc= github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw= -github.com/metacubex/quic-go v0.43.2-0.20240518033621-2c3d14c6b38e h1:Nzwe08FNIJpExWpy9iXkG336dN/8nJqn69yijB7vJ8g= -github.com/metacubex/quic-go v0.43.2-0.20240518033621-2c3d14c6b38e/go.mod h1:uXHODgJFUfUnkkCMWLd5Er6L5QY/LFRZb9LD5jyyhsk= +github.com/metacubex/quic-go v0.44.1-0.20240520163451-20b689a59136 h1:Z9XGYDs6QuSqipNcxbTx+baN/bBBAIpRxVhLpoMF42U= +github.com/metacubex/quic-go v0.44.1-0.20240520163451-20b689a59136/go.mod h1:88wAATpevav4xdy5N8oejQ2cbbI6EcLYEklFeo+qywA= github.com/metacubex/sing v0.0.0-20240518125217-e63d65a914d1 h1:7hDHLTmjgtRoAp59STwPQpe5Pinwi4cWex+FB3Ohvco= github.com/metacubex/sing v0.0.0-20240518125217-e63d65a914d1/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI= github.com/metacubex/sing-quic v0.0.0-20240518034124-7696d3f7da72 h1:Wr4g1HCb5Z/QIFwFiVNjO2qL+dRu25+Mdn9xtAZZ+ew= diff --git a/mihomo/transport/tuic/common/congestion.go b/mihomo/transport/tuic/common/congestion.go index 485e2e6a60..a0e2be68dd 100644 --- a/mihomo/transport/tuic/common/congestion.go +++ b/mihomo/transport/tuic/common/congestion.go @@ -22,7 +22,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) { quicConn.SetCongestionControl( congestion.NewCubicSender( congestion.DefaultClock{}, - congestion.GetInitialPacketSize(quicConn.RemoteAddr()), + congestion.GetInitialPacketSize(quicConn), false, ), ) @@ -30,7 +30,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) { quicConn.SetCongestionControl( congestion.NewCubicSender( congestion.DefaultClock{}, - congestion.GetInitialPacketSize(quicConn.RemoteAddr()), + congestion.GetInitialPacketSize(quicConn), true, ), ) @@ -38,7 +38,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) { quicConn.SetCongestionControl( congestion.NewBBRSender( congestion.DefaultClock{}, - congestion.GetInitialPacketSize(quicConn.RemoteAddr()), + congestion.GetInitialPacketSize(quicConn), c.ByteCount(cwnd)*congestion.InitialMaxDatagramSize, congestion.DefaultBBRMaxCongestionWindow*congestion.InitialMaxDatagramSize, ), @@ -49,7 +49,7 @@ func SetCongestionController(quicConn quic.Connection, cc string, cwnd int) { quicConn.SetCongestionControl( congestionv2.NewBbrSender( congestionv2.DefaultClock{}, - congestionv2.GetInitialPacketSize(quicConn.RemoteAddr()), + congestionv2.GetInitialPacketSize(quicConn), c.ByteCount(cwnd), ), ) diff --git a/mihomo/transport/tuic/congestion/bbr_sender.go b/mihomo/transport/tuic/congestion/bbr_sender.go index 8c18c616b7..6cea9355fb 100644 --- a/mihomo/transport/tuic/congestion/bbr_sender.go +++ b/mihomo/transport/tuic/congestion/bbr_sender.go @@ -5,34 +5,23 @@ package congestion import ( "fmt" "math" - "net" "time" + "github.com/metacubex/quic-go" "github.com/metacubex/quic-go/congestion" "github.com/zhangyunhao116/fastrand" ) const ( // InitialMaxDatagramSize is the default maximum packet size used in QUIC for congestion window computations in bytes. - InitialMaxDatagramSize = 1252 - InitialPacketSizeIPv4 = 1252 - InitialPacketSizeIPv6 = 1232 + InitialMaxDatagramSize = 1280 + InitialPacketSize = 1280 InitialCongestionWindow = 32 DefaultBBRMaxCongestionWindow = 10000 ) -func GetInitialPacketSize(addr net.Addr) congestion.ByteCount { - maxSize := congestion.ByteCount(1200) - // If this is not a UDP address, we don't know anything about the MTU. - // Use the minimum size of an Initial packet as the max packet size. - if udpAddr, ok := addr.(*net.UDPAddr); ok { - if udpAddr.IP.To4() != nil { - maxSize = InitialPacketSizeIPv4 - } else { - maxSize = InitialPacketSizeIPv6 - } - } - return congestion.ByteCount(maxSize) +func GetInitialPacketSize(quicConn quic.Connection) congestion.ByteCount { + return congestion.ByteCount(quicConn.Config().InitialPacketSize) } var ( diff --git a/mihomo/transport/tuic/congestion/cubic.go b/mihomo/transport/tuic/congestion/cubic.go index dd491a326a..a9bed43aa1 100644 --- a/mihomo/transport/tuic/congestion/cubic.go +++ b/mihomo/transport/tuic/congestion/cubic.go @@ -21,7 +21,7 @@ const ( cubeCongestionWindowScale = 410 cubeFactor congestion.ByteCount = 1 << cubeScale / cubeCongestionWindowScale / maxDatagramSize // TODO: when re-enabling cubic, make sure to use the actual packet size here - maxDatagramSize = congestion.ByteCount(InitialPacketSizeIPv4) + maxDatagramSize = congestion.ByteCount(InitialPacketSize) ) const defaultNumConnections = 1 diff --git a/mihomo/transport/tuic/congestion_v2/bbr_sender.go b/mihomo/transport/tuic/congestion_v2/bbr_sender.go index 084f85b12c..54705978cc 100644 --- a/mihomo/transport/tuic/congestion_v2/bbr_sender.go +++ b/mihomo/transport/tuic/congestion_v2/bbr_sender.go @@ -4,9 +4,9 @@ package congestion import ( "fmt" - "net" "time" + "github.com/metacubex/quic-go" "github.com/metacubex/quic-go/congestion" "github.com/zhangyunhao116/fastrand" @@ -30,7 +30,7 @@ const ( // Constants based on TCP defaults. // The minimum CWND to ensure delayed acks don't reduce bandwidth measurements. // Does not inflate the pacing rate. - defaultMinimumCongestionWindow = 4 * congestion.ByteCount(congestion.InitialPacketSizeIPv4) + defaultMinimumCongestionWindow = 4 * congestion.ByteCount(congestion.InitialPacketSize) // The gain used for the STARTUP, equal to 2/ln(2). defaultHighGain = 2.885 @@ -931,16 +931,6 @@ func bdpFromRttAndBandwidth(rtt time.Duration, bandwidth Bandwidth) congestion.B return congestion.ByteCount(rtt) * congestion.ByteCount(bandwidth) / congestion.ByteCount(BytesPerSecond) / congestion.ByteCount(time.Second) } -func GetInitialPacketSize(addr net.Addr) congestion.ByteCount { - // If this is not a UDP address, we don't know anything about the MTU. - // Use the minimum size of an Initial packet as the max packet size. - if udpAddr, ok := addr.(*net.UDPAddr); ok { - if udpAddr.IP.To4() != nil { - return congestion.InitialPacketSizeIPv4 - } else { - return congestion.InitialPacketSizeIPv6 - } - } else { - return congestion.MinInitialPacketSize - } +func GetInitialPacketSize(quicConn quic.Connection) congestion.ByteCount { + return congestion.ByteCount(quicConn.Config().InitialPacketSize) } diff --git a/mihomo/transport/tuic/congestion_v2/pacer.go b/mihomo/transport/tuic/congestion_v2/pacer.go index ecaf3d1154..174b3dbe3f 100644 --- a/mihomo/transport/tuic/congestion_v2/pacer.go +++ b/mihomo/transport/tuic/congestion_v2/pacer.go @@ -21,8 +21,8 @@ type Pacer struct { func NewPacer(getBandwidth func() congestion.ByteCount) *Pacer { p := &Pacer{ - budgetAtLastSent: maxBurstPackets * congestion.InitialPacketSizeIPv4, - maxDatagramSize: congestion.InitialPacketSizeIPv4, + budgetAtLastSent: maxBurstPackets * congestion.InitialPacketSize, + maxDatagramSize: congestion.InitialPacketSize, getBandwidth: getBandwidth, } return p diff --git a/openwrt-packages/UnblockNeteaseMusic/Makefile b/openwrt-packages/UnblockNeteaseMusic/Makefile index c55f18510e..5d3a8d925d 100644 --- a/openwrt-packages/UnblockNeteaseMusic/Makefile +++ b/openwrt-packages/UnblockNeteaseMusic/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=UnblockNeteaseMusic -PKG_VERSION:=0.27.6-patch.1 +PKG_VERSION:=0.27.7 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/UnblockNeteaseMusic/server/tar.gz/v${PKG_VERSION}? -PKG_HASH:=05b267d4f75a49e730b14505255c72dd9e6785df923e52c969ad8aa3f06380f0 +PKG_HASH:=858f0b4dd325aefe631789b23f28ad9d3b3ea0e471af82d3a9c3d7572c92e992 PKG_SOURCE_SUBDIR:=$(PKG_NAME) PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR) diff --git a/ryujinx/src/Ryujinx.Graphics.GAL/BufferAccess.cs b/ryujinx/src/Ryujinx.Graphics.GAL/BufferAccess.cs index faefa51882..1e7736f8fa 100644 --- a/ryujinx/src/Ryujinx.Graphics.GAL/BufferAccess.cs +++ b/ryujinx/src/Ryujinx.Graphics.GAL/BufferAccess.cs @@ -6,8 +6,13 @@ namespace Ryujinx.Graphics.GAL public enum BufferAccess { Default = 0, - FlushPersistent = 1 << 0, - Stream = 1 << 1, - SparseCompatible = 1 << 2, + HostMemory = 1, + DeviceMemory = 2, + DeviceMemoryMapped = 3, + + MemoryTypeMask = 0xf, + + Stream = 1 << 4, + SparseCompatible = 1 << 5, } } diff --git a/ryujinx/src/Ryujinx.Graphics.GAL/Capabilities.cs b/ryujinx/src/Ryujinx.Graphics.GAL/Capabilities.cs index 779ce5b5dc..d758586ae4 100644 --- a/ryujinx/src/Ryujinx.Graphics.GAL/Capabilities.cs +++ b/ryujinx/src/Ryujinx.Graphics.GAL/Capabilities.cs @@ -6,6 +6,7 @@ namespace Ryujinx.Graphics.GAL { public readonly TargetApi Api; public readonly string VendorName; + public readonly SystemMemoryType MemoryType; public readonly bool HasFrontFacingBug; public readonly bool HasVectorIndexingBug; @@ -66,6 +67,7 @@ namespace Ryujinx.Graphics.GAL public Capabilities( TargetApi api, string vendorName, + SystemMemoryType memoryType, bool hasFrontFacingBug, bool hasVectorIndexingBug, bool needsFragmentOutputSpecialization, @@ -120,6 +122,7 @@ namespace Ryujinx.Graphics.GAL { Api = api; VendorName = vendorName; + MemoryType = memoryType; HasFrontFacingBug = hasFrontFacingBug; HasVectorIndexingBug = hasVectorIndexingBug; NeedsFragmentOutputSpecialization = needsFragmentOutputSpecialization; diff --git a/ryujinx/src/Ryujinx.Graphics.GAL/IRenderer.cs b/ryujinx/src/Ryujinx.Graphics.GAL/IRenderer.cs index a3466e3966..85d0bd729f 100644 --- a/ryujinx/src/Ryujinx.Graphics.GAL/IRenderer.cs +++ b/ryujinx/src/Ryujinx.Graphics.GAL/IRenderer.cs @@ -17,7 +17,6 @@ namespace Ryujinx.Graphics.GAL void BackgroundContextAction(Action action, bool alwaysBackground = false); BufferHandle CreateBuffer(int size, BufferAccess access = BufferAccess.Default); - BufferHandle CreateBuffer(int size, BufferAccess access, BufferHandle storageHint); BufferHandle CreateBuffer(nint pointer, int size); BufferHandle CreateBufferSparse(ReadOnlySpan storageBuffers); diff --git a/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs b/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs index fd2919be4d..23f1a64ef9 100644 --- a/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs +++ b/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs @@ -44,7 +44,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading } Register(CommandType.Action); - Register(CommandType.CreateBuffer); Register(CommandType.CreateBufferAccess); Register(CommandType.CreateBufferSparse); Register(CommandType.CreateHostBuffer); diff --git a/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs b/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs index a5e7336cdf..f95aab05b4 100644 --- a/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs +++ b/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs @@ -3,7 +3,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading enum CommandType : byte { Action, - CreateBuffer, CreateBufferAccess, CreateBufferSparse, CreateHostBuffer, diff --git a/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs b/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs deleted file mode 100644 index 60a6e4bf45..0000000000 --- a/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Renderer -{ - struct CreateBufferCommand : IGALCommand, IGALCommand - { - public readonly CommandType CommandType => CommandType.CreateBuffer; - private BufferHandle _threadedHandle; - private int _size; - private BufferAccess _access; - private BufferHandle _storageHint; - - public void Set(BufferHandle threadedHandle, int size, BufferAccess access, BufferHandle storageHint) - { - _threadedHandle = threadedHandle; - _size = size; - _access = access; - _storageHint = storageHint; - } - - public static void Run(ref CreateBufferCommand command, ThreadedRenderer threaded, IRenderer renderer) - { - BufferHandle hint = BufferHandle.Null; - - if (command._storageHint != BufferHandle.Null) - { - hint = threaded.Buffers.MapBuffer(command._storageHint); - } - - threaded.Buffers.AssignBuffer(command._threadedHandle, renderer.CreateBuffer(command._size, command._access, hint)); - } - } -} diff --git a/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs b/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs index 5e17bcd2c1..cc3d2e5c11 100644 --- a/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs +++ b/ryujinx/src/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs @@ -272,15 +272,6 @@ namespace Ryujinx.Graphics.GAL.Multithreading return handle; } - public BufferHandle CreateBuffer(int size, BufferAccess access, BufferHandle storageHint) - { - BufferHandle handle = Buffers.CreateBufferHandle(); - New().Set(handle, size, access, storageHint); - QueueCommand(); - - return handle; - } - public BufferHandle CreateBuffer(nint pointer, int size) { BufferHandle handle = Buffers.CreateBufferHandle(); diff --git a/ryujinx/src/Ryujinx.Graphics.GAL/SystemMemoryType.cs b/ryujinx/src/Ryujinx.Graphics.GAL/SystemMemoryType.cs new file mode 100644 index 0000000000..532921298a --- /dev/null +++ b/ryujinx/src/Ryujinx.Graphics.GAL/SystemMemoryType.cs @@ -0,0 +1,29 @@ +namespace Ryujinx.Graphics.GAL +{ + public enum SystemMemoryType + { + /// + /// The backend manages the ownership of memory. This mode never supports host imported memory. + /// + BackendManaged, + + /// + /// Device memory has similar performance to host memory, usually because it's shared between CPU/GPU. + /// Use host memory whenever possible. + /// + UnifiedMemory, + + /// + /// GPU storage to host memory goes though a slow interconnect, but it would still be preferable to use it if the data is flushed back often. + /// Assumes constant buffer access to host memory is rather fast. + /// + DedicatedMemory, + + /// + /// GPU storage to host memory goes though a slow interconnect, that is very slow when doing access from storage. + /// When frequently accessed, copy buffers to host memory using DMA. + /// Assumes constant buffer access to host memory is rather fast. + /// + DedicatedMemorySlowStorage + } +} diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLE.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLE.cs index 7f3772f44b..475d1ee4e5 100644 --- a/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLE.cs +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/MME/MacroHLE.cs @@ -5,6 +5,7 @@ using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.Engine.GPFifo; using Ryujinx.Graphics.Gpu.Engine.Threed; using Ryujinx.Graphics.Gpu.Engine.Types; +using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Memory.Range; using System; using System.Collections.Generic; @@ -495,8 +496,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME ulong indirectBufferSize = (ulong)maxDrawCount * (ulong)stride; - MultiRange indirectBufferRange = bufferCache.TranslateAndCreateMultiBuffers(_processor.MemoryManager, indirectBufferGpuVa, indirectBufferSize); - MultiRange parameterBufferRange = bufferCache.TranslateAndCreateMultiBuffers(_processor.MemoryManager, parameterBufferGpuVa, 4); + MultiRange indirectBufferRange = bufferCache.TranslateAndCreateMultiBuffers(_processor.MemoryManager, indirectBufferGpuVa, indirectBufferSize, BufferStage.Indirect); + MultiRange parameterBufferRange = bufferCache.TranslateAndCreateMultiBuffers(_processor.MemoryManager, parameterBufferGpuVa, 4, BufferStage.Indirect); _processor.ThreedClass.DrawIndirect( topology, diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeContext.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeContext.cs index f9cb40b0de..6de50fb2e7 100644 --- a/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeContext.cs +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeContext.cs @@ -438,7 +438,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw ReadOnlySpan dataBytes = MemoryMarshal.Cast(data); - BufferHandle buffer = _context.Renderer.CreateBuffer(dataBytes.Length); + BufferHandle buffer = _context.Renderer.CreateBuffer(dataBytes.Length, BufferAccess.DeviceMemory); _context.Renderer.SetBufferData(buffer, 0, dataBytes); return new IndexBuffer(buffer, count, dataBytes.Length); @@ -529,7 +529,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw { if (_dummyBuffer == BufferHandle.Null) { - _dummyBuffer = _context.Renderer.CreateBuffer(DummyBufferSize); + _dummyBuffer = _context.Renderer.CreateBuffer(DummyBufferSize, BufferAccess.DeviceMemory); _context.Renderer.Pipeline.ClearBuffer(_dummyBuffer, 0, DummyBufferSize, 0); } @@ -550,7 +550,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw _context.Renderer.DeleteBuffer(_sequentialIndexBuffer); } - _sequentialIndexBuffer = _context.Renderer.CreateBuffer(count * sizeof(uint)); + _sequentialIndexBuffer = _context.Renderer.CreateBuffer(count * sizeof(uint), BufferAccess.DeviceMemory); _sequentialIndexBufferCount = count; Span data = new int[count]; @@ -583,7 +583,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw _context.Renderer.DeleteBuffer(buffer.Handle); } - buffer.Handle = _context.Renderer.CreateBuffer(newSize); + buffer.Handle = _context.Renderer.CreateBuffer(newSize, BufferAccess.DeviceMemory); buffer.Size = newSize; } diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeState.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeState.cs index 6324e6a15a..73682866ba 100644 --- a/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeState.cs +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/Threed/ComputeDraw/VtgAsComputeState.cs @@ -3,6 +3,7 @@ using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.Engine.Types; using Ryujinx.Graphics.Gpu.Image; +using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Graphics.Gpu.Shader; using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader.Translation; @@ -370,7 +371,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw { var memoryManager = _channel.MemoryManager; - BufferRange range = memoryManager.Physical.BufferCache.GetBufferRange(memoryManager.GetPhysicalRegions(address, size)); + BufferRange range = memoryManager.Physical.BufferCache.GetBufferRange(memoryManager.GetPhysicalRegions(address, size), BufferStage.VertexBuffer); ITexture bufferTexture = _vacContext.EnsureBufferTexture(index + 2, format); bufferTexture.SetStorage(range); @@ -412,7 +413,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw var memoryManager = _channel.MemoryManager; ulong misalign = address & ((ulong)_context.Capabilities.TextureBufferOffsetAlignment - 1); - BufferRange range = memoryManager.Physical.BufferCache.GetBufferRange(memoryManager.GetPhysicalRegions(address + indexOffset - misalign, size + misalign)); + BufferRange range = memoryManager.Physical.BufferCache.GetBufferRange( + memoryManager.GetPhysicalRegions(address + indexOffset - misalign, size + misalign), + BufferStage.IndexBuffer); misalignedOffset = (int)misalign >> shift; SetIndexBufferTexture(reservations, range, format); diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs index d8de14de09..56ef64c6ec 100644 --- a/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs @@ -684,8 +684,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed if (hasCount) { - var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferRange); - var parameterBuffer = memory.BufferCache.GetBufferRange(parameterBufferRange); + var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferRange, BufferStage.Indirect); + var parameterBuffer = memory.BufferCache.GetBufferRange(parameterBufferRange, BufferStage.Indirect); if (indexed) { @@ -698,7 +698,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed } else { - var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferRange); + var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferRange, BufferStage.Indirect); if (indexed) { diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/GpuContext.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/GpuContext.cs index 53ea8cb277..048d32fb79 100644 --- a/ryujinx/src/Ryujinx.Graphics.Gpu/GpuContext.cs +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/GpuContext.cs @@ -393,17 +393,18 @@ namespace Ryujinx.Graphics.Gpu if (force || _pendingSync || (syncpoint && SyncpointActions.Count > 0)) { - Renderer.CreateSync(SyncNumber, strict); - foreach (var action in SyncActions) { action.SyncPreAction(syncpoint); } + foreach (var action in SyncpointActions) { action.SyncPreAction(syncpoint); } + Renderer.CreateSync(SyncNumber, strict); + SyncNumber++; SyncActions.RemoveAll(action => action.SyncAction(syncpoint)); diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs index 7e486e0a84..a54d070004 100644 --- a/ryujinx/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs @@ -708,11 +708,11 @@ namespace Ryujinx.Graphics.Gpu.Image format = texture.Format; } - _channel.BufferManager.SetBufferTextureStorage(entry.ImageArray, hostTexture, texture.Range, bindingInfo, index, format); + _channel.BufferManager.SetBufferTextureStorage(stage, entry.ImageArray, hostTexture, texture.Range, bindingInfo, index, format); } else { - _channel.BufferManager.SetBufferTextureStorage(entry.TextureArray, hostTexture, texture.Range, bindingInfo, index, format); + _channel.BufferManager.SetBufferTextureStorage(stage, entry.TextureArray, hostTexture, texture.Range, bindingInfo, index, format); } } else if (isImage) @@ -921,11 +921,11 @@ namespace Ryujinx.Graphics.Gpu.Image format = texture.Format; } - _channel.BufferManager.SetBufferTextureStorage(entry.ImageArray, hostTexture, texture.Range, bindingInfo, index, format); + _channel.BufferManager.SetBufferTextureStorage(stage, entry.ImageArray, hostTexture, texture.Range, bindingInfo, index, format); } else { - _channel.BufferManager.SetBufferTextureStorage(entry.TextureArray, hostTexture, texture.Range, bindingInfo, index, format); + _channel.BufferManager.SetBufferTextureStorage(stage, entry.TextureArray, hostTexture, texture.Range, bindingInfo, index, format); } } else if (isImage) diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs index 4e1133d1af..06ca2c5997 100644 --- a/ryujinx/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs @@ -645,7 +645,7 @@ namespace Ryujinx.Graphics.Gpu.Image } else { - _flushBuffer = _context.Renderer.CreateBuffer((int)Storage.Size, BufferAccess.FlushPersistent); + _flushBuffer = _context.Renderer.CreateBuffer((int)Storage.Size, BufferAccess.HostMemory); _flushBufferImported = false; } diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs index d293060b5a..e060e0b4f8 100644 --- a/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs @@ -10,6 +10,8 @@ using System.Threading; namespace Ryujinx.Graphics.Gpu.Memory { + delegate void BufferFlushAction(ulong address, ulong size, ulong syncNumber); + /// /// Buffer, used to store vertex and index data, uniform and storage buffers, and others. /// @@ -23,7 +25,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Host buffer handle. /// - public BufferHandle Handle { get; } + public BufferHandle Handle { get; private set; } /// /// Start address of the buffer in guest memory. @@ -60,6 +62,17 @@ namespace Ryujinx.Graphics.Gpu.Memory /// private BufferModifiedRangeList _modifiedRanges = null; + /// + /// A structure that is used to flush buffer data back to a host mapped buffer for cached readback. + /// Only used if the buffer data is explicitly owned by device local memory. + /// + private BufferPreFlush _preFlush = null; + + /// + /// Usage tracking state that determines what type of backing the buffer should use. + /// + public BufferBackingState BackingState; + private readonly MultiRegionHandle _memoryTrackingGranular; private readonly RegionHandle _memoryTracking; @@ -87,6 +100,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Physical memory where the buffer is mapped /// Start address of the buffer /// Size of the buffer in bytes + /// The type of usage that created the buffer /// Indicates if the buffer can be used in a sparse buffer mapping /// Buffers which this buffer contains, and will inherit tracking handles from public Buffer( @@ -94,6 +108,7 @@ namespace Ryujinx.Graphics.Gpu.Memory PhysicalMemory physicalMemory, ulong address, ulong size, + BufferStage stage, bool sparseCompatible, IEnumerable baseBuffers = null) { @@ -103,9 +118,11 @@ namespace Ryujinx.Graphics.Gpu.Memory Size = size; SparseCompatible = sparseCompatible; - BufferAccess access = sparseCompatible ? BufferAccess.SparseCompatible : BufferAccess.Default; + BackingState = new BufferBackingState(_context, this, stage, baseBuffers); - Handle = context.Renderer.CreateBuffer((int)size, access, baseBuffers?.MaxBy(x => x.Size).Handle ?? BufferHandle.Null); + BufferAccess access = BackingState.SwitchAccess(this); + + Handle = context.Renderer.CreateBuffer((int)size, access); _useGranular = size > GranularBufferThreshold; @@ -161,6 +178,29 @@ namespace Ryujinx.Graphics.Gpu.Memory _virtualDependenciesLock = new ReaderWriterLockSlim(); } + /// + /// Recreates the backing buffer based on the desired access type + /// reported by the backing state struct. + /// + private void ChangeBacking() + { + BufferAccess access = BackingState.SwitchAccess(this); + + BufferHandle newHandle = _context.Renderer.CreateBuffer((int)Size, access); + + _context.Renderer.Pipeline.CopyBuffer(Handle, newHandle, 0, 0, (int)Size); + + _modifiedRanges?.SelfMigration(); + + // If swtiching from device local to host mapped, pre-flushing data no longer makes sense. + // This is set to null and disposed when the migration fully completes. + _preFlush = null; + + Handle = newHandle; + + _physicalMemory.BufferCache.BufferBackingChanged(this); + } + /// /// Gets a sub-range from the buffer, from a start address til a page boundary after the given size. /// @@ -246,6 +286,7 @@ namespace Ryujinx.Graphics.Gpu.Memory } else { + BackingState.RecordSet(); _context.Renderer.SetBufferData(Handle, 0, _physicalMemory.GetSpan(Address, (int)Size)); CopyToDependantVirtualBuffers(); } @@ -283,15 +324,35 @@ namespace Ryujinx.Graphics.Gpu.Memory _modifiedRanges ??= new BufferModifiedRangeList(_context, this, Flush); } + /// + /// Checks if a backing change is deemed necessary from the given usage. + /// If it is, queues a backing change to happen on the next sync action. + /// + /// Buffer stage that can change backing type + private void TryQueueBackingChange(BufferStage stage) + { + if (BackingState.ShouldChangeBacking(stage)) + { + if (!_syncActionRegistered) + { + _context.RegisterSyncAction(this); + _syncActionRegistered = true; + } + } + } + /// /// Signal that the given region of the buffer has been modified. /// /// The start address of the modified region /// The size of the modified region - public void SignalModified(ulong address, ulong size) + /// Buffer stage that triggered the modification + public void SignalModified(ulong address, ulong size, BufferStage stage) { EnsureRangeList(); + TryQueueBackingChange(stage); + _modifiedRanges.SignalModified(address, size); if (!_syncActionRegistered) @@ -311,6 +372,37 @@ namespace Ryujinx.Graphics.Gpu.Memory _modifiedRanges?.Clear(address, size); } + /// + /// Action to be performed immediately before sync is created. + /// This will copy any buffer ranges designated for pre-flushing. + /// + /// True if the action is a guest syncpoint + public void SyncPreAction(bool syncpoint) + { + if (_referenceCount == 0) + { + return; + } + + if (BackingState.ShouldChangeBacking()) + { + ChangeBacking(); + } + + if (BackingState.IsDeviceLocal) + { + _preFlush ??= new BufferPreFlush(_context, this, FlushImpl); + + if (_preFlush.ShouldCopy) + { + _modifiedRanges?.GetRangesAtSync(Address, Size, _context.SyncNumber, (address, size) => + { + _preFlush.CopyModified(address, size); + }); + } + } + } + /// /// Action to be performed when a syncpoint is reached after modification. /// This will register read/write tracking to flush the buffer from GPU when its memory is used. @@ -466,6 +558,8 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Size of the modified region private void LoadRegion(ulong mAddress, ulong mSize) { + BackingState.RecordSet(); + int offset = (int)(mAddress - Address); _context.Renderer.SetBufferData(Handle, offset, _physicalMemory.GetSpan(mAddress, (int)mSize)); @@ -539,18 +633,84 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Flushes a range of the buffer. /// This writes the range data back into guest memory. /// + /// Buffer handle to flush data from /// Start address of the range /// Size in bytes of the range - public void Flush(ulong address, ulong size) + private void FlushImpl(BufferHandle handle, ulong address, ulong size) { int offset = (int)(address - Address); - using PinnedSpan data = _context.Renderer.GetBufferData(Handle, offset, (int)size); + using PinnedSpan data = _context.Renderer.GetBufferData(handle, offset, (int)size); // TODO: When write tracking shaders, they will need to be aware of changes in overlapping buffers. _physicalMemory.WriteUntracked(address, CopyFromDependantVirtualBuffers(data.Get(), address, size)); } + /// + /// Flushes a range of the buffer. + /// This writes the range data back into guest memory. + /// + /// Start address of the range + /// Size in bytes of the range + private void FlushImpl(ulong address, ulong size) + { + FlushImpl(Handle, address, size); + } + + /// + /// Flushes a range of the buffer from the most optimal source. + /// This writes the range data back into guest memory. + /// + /// Start address of the range + /// Size in bytes of the range + /// Sync number waited for before flushing the data + public void Flush(ulong address, ulong size, ulong syncNumber) + { + BackingState.RecordFlush(); + + BufferPreFlush preFlush = _preFlush; + + if (preFlush != null) + { + preFlush.FlushWithAction(address, size, syncNumber); + } + else + { + FlushImpl(address, size); + } + } + /// + /// Gets an action that disposes the backing buffer using its current handle. + /// Useful for deleting an old copy of the buffer after the handle changes. + /// + /// An action that flushes data from the specified range, using the buffer handle at the time the method is generated + public Action GetSnapshotDisposeAction() + { + BufferHandle handle = Handle; + BufferPreFlush preFlush = _preFlush; + + return () => + { + _context.Renderer.DeleteBuffer(handle); + preFlush?.Dispose(); + }; + } + + /// + /// Gets an action that flushes a range of the buffer using its current handle. + /// Useful for flushing data from old copies of the buffer after the handle changes. + /// + /// An action that flushes data from the specified range, using the buffer handle at the time the method is generated + public BufferFlushAction GetSnapshotFlushAction() + { + BufferHandle handle = Handle; + + return (ulong address, ulong size, ulong _) => + { + FlushImpl(handle, address, size); + }; + } + /// /// Align a given address and size region to page boundaries. /// @@ -857,6 +1017,8 @@ namespace Ryujinx.Graphics.Gpu.Memory _modifiedRanges?.Clear(); _context.Renderer.DeleteBuffer(Handle); + _preFlush?.Dispose(); + _preFlush = null; UnmappedSequence++; } diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs new file mode 100644 index 0000000000..3f65131e6b --- /dev/null +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs @@ -0,0 +1,294 @@ +using Ryujinx.Graphics.GAL; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Graphics.Gpu.Memory +{ + /// + /// Type of backing memory. + /// In ascending order of priority when merging multiple buffer backing states. + /// + internal enum BufferBackingType + { + HostMemory, + DeviceMemory, + DeviceMemoryWithFlush + } + + /// + /// Keeps track of buffer usage to decide what memory heap that buffer memory is placed on. + /// Dedicated GPUs prefer certain types of resources to be device local, + /// and if we need data to be read back, we might prefer that they're in host memory. + /// + /// The measurements recorded here compare to a set of heruristics (thresholds and conditions) + /// that appear to produce good performance in most software. + /// + internal struct BufferBackingState + { + private const int DeviceLocalSizeThreshold = 256 * 1024; // 256kb + + private const int SetCountThreshold = 100; + private const int WriteCountThreshold = 50; + private const int FlushCountThreshold = 5; + private const int DeviceLocalForceExpiry = 100; + + public readonly bool IsDeviceLocal => _activeType != BufferBackingType.HostMemory; + + private readonly SystemMemoryType _systemMemoryType; + private BufferBackingType _activeType; + private BufferBackingType _desiredType; + + private bool _canSwap; + + private int _setCount; + private int _writeCount; + private int _flushCount; + private int _flushTemp; + private int _lastFlushWrite; + private int _deviceLocalForceCount; + + private readonly int _size; + + /// + /// Initialize the buffer backing state for a given parent buffer. + /// + /// GPU context + /// Parent buffer + /// Initial buffer stage + /// Buffers to inherit state from + public BufferBackingState(GpuContext context, Buffer parent, BufferStage stage, IEnumerable baseBuffers = null) + { + _size = (int)parent.Size; + _systemMemoryType = context.Capabilities.MemoryType; + + // Backend managed is always auto, unified memory is always host. + _desiredType = BufferBackingType.HostMemory; + _canSwap = _systemMemoryType != SystemMemoryType.BackendManaged && _systemMemoryType != SystemMemoryType.UnifiedMemory; + + if (_canSwap) + { + // Might want to start certain buffers as being device local, + // and the usage might also lock those buffers into being device local. + + BufferStage storageFlags = stage & BufferStage.StorageMask; + + if (parent.Size > DeviceLocalSizeThreshold && baseBuffers == null) + { + _desiredType = BufferBackingType.DeviceMemory; + } + + if (storageFlags != 0) + { + // Storage buffer bindings may require special treatment. + + var rawStage = stage & BufferStage.StageMask; + + if (rawStage == BufferStage.Fragment) + { + // Fragment read should start device local. + + _desiredType = BufferBackingType.DeviceMemory; + + if (storageFlags != BufferStage.StorageRead) + { + // Fragment write should stay device local until the use doesn't happen anymore. + + _deviceLocalForceCount = DeviceLocalForceExpiry; + } + } + + // TODO: Might be nice to force atomic access to be device local for any stage. + } + + if (baseBuffers != null) + { + foreach (Buffer buffer in baseBuffers) + { + CombineState(buffer.BackingState); + } + } + } + } + + /// + /// Combine buffer backing types, selecting the one with highest priority. + /// + /// First buffer backing type + /// Second buffer backing type + /// Combined buffer backing type + private static BufferBackingType CombineTypes(BufferBackingType left, BufferBackingType right) + { + return (BufferBackingType)Math.Max((int)left, (int)right); + } + + /// + /// Combine the state from the given buffer backing state with this one, + /// so that the state isn't lost when migrating buffers. + /// + /// Buffer state to combine into this state + private void CombineState(BufferBackingState oldState) + { + _setCount += oldState._setCount; + _writeCount += oldState._writeCount; + _flushCount += oldState._flushCount; + _flushTemp += oldState._flushTemp; + _lastFlushWrite = -1; + _deviceLocalForceCount = Math.Max(_deviceLocalForceCount, oldState._deviceLocalForceCount); + + _canSwap &= oldState._canSwap; + + _desiredType = CombineTypes(_desiredType, oldState._desiredType); + } + + /// + /// Get the buffer access for the desired backing type, and record that type as now being active. + /// + /// Parent buffer + /// Buffer access + public BufferAccess SwitchAccess(Buffer parent) + { + BufferAccess access = parent.SparseCompatible ? BufferAccess.SparseCompatible : BufferAccess.Default; + + bool isBackendManaged = _systemMemoryType == SystemMemoryType.BackendManaged; + + if (!isBackendManaged) + { + switch (_desiredType) + { + case BufferBackingType.HostMemory: + access |= BufferAccess.HostMemory; + break; + case BufferBackingType.DeviceMemory: + access |= BufferAccess.DeviceMemory; + break; + case BufferBackingType.DeviceMemoryWithFlush: + access |= BufferAccess.DeviceMemoryMapped; + break; + } + } + + _activeType = _desiredType; + + return access; + } + + /// + /// Record when data has been uploaded to the buffer. + /// + public void RecordSet() + { + _setCount++; + + ConsiderUseCounts(); + } + + /// + /// Record when data has been flushed from the buffer. + /// + public void RecordFlush() + { + if (_lastFlushWrite != _writeCount) + { + // If it's on the same page as the last flush, ignore it. + _lastFlushWrite = _writeCount; + _flushCount++; + } + } + + /// + /// Determine if the buffer backing should be changed. + /// + /// True if the desired backing type is different from the current type + public readonly bool ShouldChangeBacking() + { + return _desiredType != _activeType; + } + + /// + /// Determine if the buffer backing should be changed, considering a new use with the given buffer stage. + /// + /// Buffer stage for the use + /// True if the desired backing type is different from the current type + public bool ShouldChangeBacking(BufferStage stage) + { + if (!_canSwap) + { + return false; + } + + BufferStage storageFlags = stage & BufferStage.StorageMask; + + if (storageFlags != 0) + { + if (storageFlags != BufferStage.StorageRead) + { + // Storage write. + _writeCount++; + + var rawStage = stage & BufferStage.StageMask; + + if (rawStage == BufferStage.Fragment) + { + // Switch to device memory, swap back only if this use disappears. + + _desiredType = CombineTypes(_desiredType, BufferBackingType.DeviceMemory); + _deviceLocalForceCount = DeviceLocalForceExpiry; + + // TODO: Might be nice to force atomic access to be device local for any stage. + } + } + + ConsiderUseCounts(); + } + + return _desiredType != _activeType; + } + + /// + /// Evaluate the current counts to determine what the buffer's desired backing type is. + /// This method depends on heuristics devised by testing a variety of software. + /// + private void ConsiderUseCounts() + { + if (_canSwap) + { + if (_writeCount >= WriteCountThreshold || _setCount >= SetCountThreshold || _flushCount >= FlushCountThreshold) + { + if (_deviceLocalForceCount > 0 && --_deviceLocalForceCount != 0) + { + // Some buffer usage demanded that the buffer stay device local. + // The desired type was selected when this counter was set. + } + else if (_flushCount > 0 || _flushTemp-- > 0) + { + // Buffers that flush should ideally be mapped in host address space for easy copies. + // If the buffer is large it will do better on GPU memory, as there will be more writes than data flushes (typically individual pages). + // If it is small, then it's likely most of the buffer will be flushed so we want it on host memory, as access is cached. + _desiredType = _size > DeviceLocalSizeThreshold ? BufferBackingType.DeviceMemoryWithFlush : BufferBackingType.HostMemory; + } + else if (_writeCount >= WriteCountThreshold) + { + // Buffers that are written often should ideally be in the device local heap. (Storage buffers) + _desiredType = BufferBackingType.DeviceMemory; + } + else if (_setCount > SetCountThreshold) + { + // Buffers that have their data set often should ideally be host mapped. (Constant buffers) + _desiredType = BufferBackingType.HostMemory; + } + + // It's harder for a buffer that is flushed to revert to another type of mapping. + if (_flushCount > 0) + { + _flushTemp = 1000; + } + + _lastFlushWrite = -1; + _flushCount = 0; + _writeCount = 0; + _setCount = 0; + } + } + } + } +} diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs index c6284780d3..66d2cdb626 100644 --- a/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs @@ -107,8 +107,9 @@ namespace Ryujinx.Graphics.Gpu.Memory /// GPU memory manager where the buffer is mapped /// Start GPU virtual address of the buffer /// Size in bytes of the buffer + /// The type of usage that created the buffer /// Contiguous physical range of the buffer, after address translation - public MultiRange TranslateAndCreateBuffer(MemoryManager memoryManager, ulong gpuVa, ulong size) + public MultiRange TranslateAndCreateBuffer(MemoryManager memoryManager, ulong gpuVa, ulong size, BufferStage stage) { if (gpuVa == 0) { @@ -119,7 +120,7 @@ namespace Ryujinx.Graphics.Gpu.Memory if (address != MemoryManager.PteUnmapped) { - CreateBuffer(address, size); + CreateBuffer(address, size, stage); } return new MultiRange(address, size); @@ -132,8 +133,9 @@ namespace Ryujinx.Graphics.Gpu.Memory /// GPU memory manager where the buffer is mapped /// Start GPU virtual address of the buffer /// Size in bytes of the buffer + /// The type of usage that created the buffer /// Physical ranges of the buffer, after address translation - public MultiRange TranslateAndCreateMultiBuffers(MemoryManager memoryManager, ulong gpuVa, ulong size) + public MultiRange TranslateAndCreateMultiBuffers(MemoryManager memoryManager, ulong gpuVa, ulong size, BufferStage stage) { if (gpuVa == 0) { @@ -149,7 +151,7 @@ namespace Ryujinx.Graphics.Gpu.Memory return range; } - CreateBuffer(range); + CreateBuffer(range, stage); return range; } @@ -161,8 +163,9 @@ namespace Ryujinx.Graphics.Gpu.Memory /// GPU memory manager where the buffer is mapped /// Start GPU virtual address of the buffer /// Size in bytes of the buffer + /// The type of usage that created the buffer /// Physical ranges of the buffer, after address translation - public MultiRange TranslateAndCreateMultiBuffersPhysicalOnly(MemoryManager memoryManager, ulong gpuVa, ulong size) + public MultiRange TranslateAndCreateMultiBuffersPhysicalOnly(MemoryManager memoryManager, ulong gpuVa, ulong size, BufferStage stage) { if (gpuVa == 0) { @@ -186,11 +189,11 @@ namespace Ryujinx.Graphics.Gpu.Memory { if (range.Count > 1) { - CreateBuffer(subRange.Address, subRange.Size, SparseBufferAlignmentSize); + CreateBuffer(subRange.Address, subRange.Size, stage, SparseBufferAlignmentSize); } else { - CreateBuffer(subRange.Address, subRange.Size); + CreateBuffer(subRange.Address, subRange.Size, stage); } } } @@ -203,11 +206,12 @@ namespace Ryujinx.Graphics.Gpu.Memory /// This can be used to ensure the existance of a buffer. /// /// Physical ranges of memory where the buffer data is located - public void CreateBuffer(MultiRange range) + /// The type of usage that created the buffer + public void CreateBuffer(MultiRange range, BufferStage stage) { if (range.Count > 1) { - CreateMultiRangeBuffer(range); + CreateMultiRangeBuffer(range, stage); } else { @@ -215,7 +219,7 @@ namespace Ryujinx.Graphics.Gpu.Memory if (subRange.Address != MemoryManager.PteUnmapped) { - CreateBuffer(subRange.Address, subRange.Size); + CreateBuffer(subRange.Address, subRange.Size, stage); } } } @@ -226,7 +230,8 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Address of the buffer in memory /// Size of the buffer in bytes - public void CreateBuffer(ulong address, ulong size) + /// The type of usage that created the buffer + public void CreateBuffer(ulong address, ulong size, BufferStage stage) { ulong endAddress = address + size; @@ -239,7 +244,7 @@ namespace Ryujinx.Graphics.Gpu.Memory alignedEndAddress += BufferAlignmentSize; } - CreateBufferAligned(alignedAddress, alignedEndAddress - alignedAddress); + CreateBufferAligned(alignedAddress, alignedEndAddress - alignedAddress, stage); } /// @@ -248,8 +253,9 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Address of the buffer in memory /// Size of the buffer in bytes + /// The type of usage that created the buffer /// Alignment of the start address of the buffer in bytes - public void CreateBuffer(ulong address, ulong size, ulong alignment) + public void CreateBuffer(ulong address, ulong size, BufferStage stage, ulong alignment) { ulong alignmentMask = alignment - 1; ulong pageAlignmentMask = BufferAlignmentMask; @@ -264,7 +270,7 @@ namespace Ryujinx.Graphics.Gpu.Memory alignedEndAddress += pageAlignmentMask; } - CreateBufferAligned(alignedAddress, alignedEndAddress - alignedAddress, alignment); + CreateBufferAligned(alignedAddress, alignedEndAddress - alignedAddress, stage, alignment); } /// @@ -272,7 +278,8 @@ namespace Ryujinx.Graphics.Gpu.Memory /// if it does not exist yet. /// /// Physical ranges of memory - private void CreateMultiRangeBuffer(MultiRange range) + /// The type of usage that created the buffer + private void CreateMultiRangeBuffer(MultiRange range, BufferStage stage) { // Ensure all non-contiguous buffer we might use are sparse aligned. for (int i = 0; i < range.Count; i++) @@ -281,7 +288,7 @@ namespace Ryujinx.Graphics.Gpu.Memory if (subRange.Address != MemoryManager.PteUnmapped) { - CreateBuffer(subRange.Address, subRange.Size, SparseBufferAlignmentSize); + CreateBuffer(subRange.Address, subRange.Size, stage, SparseBufferAlignmentSize); } } @@ -431,9 +438,9 @@ namespace Ryujinx.Graphics.Gpu.Memory result.EndGpuAddress < gpuVa + size || result.UnmappedSequence != result.Buffer.UnmappedSequence) { - MultiRange range = TranslateAndCreateBuffer(memoryManager, gpuVa, size); + MultiRange range = TranslateAndCreateBuffer(memoryManager, gpuVa, size, BufferStage.Internal); ulong address = range.GetSubRange(0).Address; - result = new BufferCacheEntry(address, gpuVa, GetBuffer(address, size)); + result = new BufferCacheEntry(address, gpuVa, GetBuffer(address, size, BufferStage.Internal)); _dirtyCache[gpuVa] = result; } @@ -466,9 +473,9 @@ namespace Ryujinx.Graphics.Gpu.Memory result.EndGpuAddress < alignedEndGpuVa || result.UnmappedSequence != result.Buffer.UnmappedSequence) { - MultiRange range = TranslateAndCreateBuffer(memoryManager, alignedGpuVa, size); + MultiRange range = TranslateAndCreateBuffer(memoryManager, alignedGpuVa, size, BufferStage.None); ulong address = range.GetSubRange(0).Address; - result = new BufferCacheEntry(address, alignedGpuVa, GetBuffer(address, size)); + result = new BufferCacheEntry(address, alignedGpuVa, GetBuffer(address, size, BufferStage.None)); _modifiedCache[alignedGpuVa] = result; } @@ -485,7 +492,8 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Address of the buffer in guest memory /// Size in bytes of the buffer - private void CreateBufferAligned(ulong address, ulong size) + /// The type of usage that created the buffer + private void CreateBufferAligned(ulong address, ulong size, BufferStage stage) { Buffer[] overlaps = _bufferOverlaps; int overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps); @@ -546,13 +554,13 @@ namespace Ryujinx.Graphics.Gpu.Memory ulong newSize = endAddress - address; - CreateBufferAligned(address, newSize, anySparseCompatible, overlaps, overlapsCount); + CreateBufferAligned(address, newSize, stage, anySparseCompatible, overlaps, overlapsCount); } } else { // No overlap, just create a new buffer. - Buffer buffer = new(_context, _physicalMemory, address, size, sparseCompatible: false); + Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible: false); lock (_buffers) { @@ -570,8 +578,9 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Address of the buffer in guest memory /// Size in bytes of the buffer + /// The type of usage that created the buffer /// Alignment of the start address of the buffer - private void CreateBufferAligned(ulong address, ulong size, ulong alignment) + private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, ulong alignment) { Buffer[] overlaps = _bufferOverlaps; int overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps); @@ -624,13 +633,13 @@ namespace Ryujinx.Graphics.Gpu.Memory ulong newSize = endAddress - address; - CreateBufferAligned(address, newSize, sparseAligned, overlaps, overlapsCount); + CreateBufferAligned(address, newSize, stage, sparseAligned, overlaps, overlapsCount); } } else { // No overlap, just create a new buffer. - Buffer buffer = new(_context, _physicalMemory, address, size, sparseAligned); + Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseAligned); lock (_buffers) { @@ -648,12 +657,13 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Address of the buffer in guest memory /// Size in bytes of the buffer + /// The type of usage that created the buffer /// Indicates if the buffer can be used in a sparse buffer mapping /// Buffers overlapping the range /// Total of overlaps - private void CreateBufferAligned(ulong address, ulong size, bool sparseCompatible, Buffer[] overlaps, int overlapsCount) + private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, bool sparseCompatible, Buffer[] overlaps, int overlapsCount) { - Buffer newBuffer = new Buffer(_context, _physicalMemory, address, size, sparseCompatible, overlaps.Take(overlapsCount)); + Buffer newBuffer = new Buffer(_context, _physicalMemory, address, size, stage, sparseCompatible, overlaps.Take(overlapsCount)); lock (_buffers) { @@ -704,7 +714,7 @@ namespace Ryujinx.Graphics.Gpu.Memory for (int index = 0; index < overlapCount; index++) { - CreateMultiRangeBuffer(overlaps[index].Range); + CreateMultiRangeBuffer(overlaps[index].Range, BufferStage.None); } } @@ -731,8 +741,8 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Size in bytes of the copy public void CopyBuffer(MemoryManager memoryManager, ulong srcVa, ulong dstVa, ulong size) { - MultiRange srcRange = TranslateAndCreateMultiBuffersPhysicalOnly(memoryManager, srcVa, size); - MultiRange dstRange = TranslateAndCreateMultiBuffersPhysicalOnly(memoryManager, dstVa, size); + MultiRange srcRange = TranslateAndCreateMultiBuffersPhysicalOnly(memoryManager, srcVa, size, BufferStage.Copy); + MultiRange dstRange = TranslateAndCreateMultiBuffersPhysicalOnly(memoryManager, dstVa, size, BufferStage.Copy); if (srcRange.Count == 1 && dstRange.Count == 1) { @@ -788,8 +798,8 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Size in bytes of the copy private void CopyBufferSingleRange(MemoryManager memoryManager, ulong srcAddress, ulong dstAddress, ulong size) { - Buffer srcBuffer = GetBuffer(srcAddress, size); - Buffer dstBuffer = GetBuffer(dstAddress, size); + Buffer srcBuffer = GetBuffer(srcAddress, size, BufferStage.Copy); + Buffer dstBuffer = GetBuffer(dstAddress, size, BufferStage.Copy); int srcOffset = (int)(srcAddress - srcBuffer.Address); int dstOffset = (int)(dstAddress - dstBuffer.Address); @@ -803,7 +813,7 @@ namespace Ryujinx.Graphics.Gpu.Memory if (srcBuffer.IsModified(srcAddress, size)) { - dstBuffer.SignalModified(dstAddress, size); + dstBuffer.SignalModified(dstAddress, size, BufferStage.Copy); } else { @@ -828,12 +838,12 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Value to be written into the buffer public void ClearBuffer(MemoryManager memoryManager, ulong gpuVa, ulong size, uint value) { - MultiRange range = TranslateAndCreateMultiBuffersPhysicalOnly(memoryManager, gpuVa, size); + MultiRange range = TranslateAndCreateMultiBuffersPhysicalOnly(memoryManager, gpuVa, size, BufferStage.Copy); for (int index = 0; index < range.Count; index++) { MemoryRange subRange = range.GetSubRange(index); - Buffer buffer = GetBuffer(subRange.Address, subRange.Size); + Buffer buffer = GetBuffer(subRange.Address, subRange.Size, BufferStage.Copy); int offset = (int)(subRange.Address - buffer.Address); @@ -849,18 +859,19 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Gets a buffer sub-range starting at a given memory address, aligned to the next page boundary. /// /// Physical regions of memory where the buffer is mapped + /// Buffer stage that triggered the access /// Whether the buffer will be written to by this use /// The buffer sub-range starting at the given memory address - public BufferRange GetBufferRangeAligned(MultiRange range, bool write = false) + public BufferRange GetBufferRangeAligned(MultiRange range, BufferStage stage, bool write = false) { if (range.Count > 1) { - return GetBuffer(range, write).GetRange(range); + return GetBuffer(range, stage, write).GetRange(range); } else { MemoryRange subRange = range.GetSubRange(0); - return GetBuffer(subRange.Address, subRange.Size, write).GetRangeAligned(subRange.Address, subRange.Size, write); + return GetBuffer(subRange.Address, subRange.Size, stage, write).GetRangeAligned(subRange.Address, subRange.Size, write); } } @@ -868,18 +879,19 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Gets a buffer sub-range for a given memory range. /// /// Physical regions of memory where the buffer is mapped + /// Buffer stage that triggered the access /// Whether the buffer will be written to by this use /// The buffer sub-range for the given range - public BufferRange GetBufferRange(MultiRange range, bool write = false) + public BufferRange GetBufferRange(MultiRange range, BufferStage stage, bool write = false) { if (range.Count > 1) { - return GetBuffer(range, write).GetRange(range); + return GetBuffer(range, stage, write).GetRange(range); } else { MemoryRange subRange = range.GetSubRange(0); - return GetBuffer(subRange.Address, subRange.Size, write).GetRange(subRange.Address, subRange.Size, write); + return GetBuffer(subRange.Address, subRange.Size, stage, write).GetRange(subRange.Address, subRange.Size, write); } } @@ -888,9 +900,10 @@ namespace Ryujinx.Graphics.Gpu.Memory /// A buffer overlapping with the specified range is assumed to already exist on the cache. /// /// Physical regions of memory where the buffer is mapped + /// Buffer stage that triggered the access /// Whether the buffer will be written to by this use /// The buffer where the range is fully contained - private MultiRangeBuffer GetBuffer(MultiRange range, bool write = false) + private MultiRangeBuffer GetBuffer(MultiRange range, BufferStage stage, bool write = false) { for (int i = 0; i < range.Count; i++) { @@ -902,7 +915,7 @@ namespace Ryujinx.Graphics.Gpu.Memory if (write) { - subBuffer.SignalModified(subRange.Address, subRange.Size); + subBuffer.SignalModified(subRange.Address, subRange.Size, stage); } } @@ -935,9 +948,10 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Start address of the memory range /// Size in bytes of the memory range + /// Buffer stage that triggered the access /// Whether the buffer will be written to by this use /// The buffer where the range is fully contained - private Buffer GetBuffer(ulong address, ulong size, bool write = false) + private Buffer GetBuffer(ulong address, ulong size, BufferStage stage, bool write = false) { Buffer buffer; @@ -950,7 +964,7 @@ namespace Ryujinx.Graphics.Gpu.Memory if (write) { - buffer.SignalModified(address, size); + buffer.SignalModified(address, size, stage); } } else @@ -1004,6 +1018,18 @@ namespace Ryujinx.Graphics.Gpu.Memory } } + /// + /// Signal that the given buffer's handle has changed, + /// forcing rebind and any overlapping multi-range buffers to be recreated. + /// + /// The buffer that has changed handle + public void BufferBackingChanged(Buffer buffer) + { + NotifyBuffersModified?.Invoke(); + + RecreateMultiRangeBuffers(buffer.Address, buffer.Size); + } + /// /// Prune any invalid entries from a quick access dictionary. /// diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs index 8f2201e0aa..26d9501c68 100644 --- a/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs @@ -156,7 +156,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Type of each index buffer element public void SetIndexBuffer(ulong gpuVa, ulong size, IndexType type) { - MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size); + MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size, BufferStage.IndexBuffer); _indexBuffer.Range = range; _indexBuffer.Type = type; @@ -186,7 +186,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Vertex divisor of the buffer, for instanced draws public void SetVertexBuffer(int index, ulong gpuVa, ulong size, int stride, int divisor) { - MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size); + MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size, BufferStage.VertexBuffer); _vertexBuffers[index].Range = range; _vertexBuffers[index].Stride = stride; @@ -213,7 +213,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Size in bytes of the transform feedback buffer public void SetTransformFeedbackBuffer(int index, ulong gpuVa, ulong size) { - MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size); + MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size, BufferStage.TransformFeedback); _transformFeedbackBuffers[index] = new BufferBounds(range); _transformFeedbackBuffersDirty = true; @@ -260,7 +260,7 @@ namespace Ryujinx.Graphics.Gpu.Memory gpuVa = BitUtils.AlignDown(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment); - MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size); + MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size, BufferStageUtils.ComputeStorage(flags)); _cpStorageBuffers.SetBounds(index, range, flags); } @@ -284,7 +284,7 @@ namespace Ryujinx.Graphics.Gpu.Memory gpuVa = BitUtils.AlignDown(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment); - MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size); + MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateMultiBuffers(_channel.MemoryManager, gpuVa, size, BufferStageUtils.GraphicsStorage(stage, flags)); if (!buffers.Buffers[index].Range.Equals(range)) { @@ -303,7 +303,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Size in bytes of the storage buffer public void SetComputeUniformBuffer(int index, ulong gpuVa, ulong size) { - MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size); + MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size, BufferStage.Compute); _cpUniformBuffers.SetBounds(index, range); } @@ -318,7 +318,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Size in bytes of the storage buffer public void SetGraphicsUniformBuffer(int stage, int index, ulong gpuVa, ulong size) { - MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size); + MultiRange range = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size, BufferStageUtils.FromShaderStage(stage)); _gpUniformBuffers[stage].SetBounds(index, range); _gpUniformBuffersDirty = true; @@ -502,7 +502,7 @@ namespace Ryujinx.Graphics.Gpu.Memory foreach (var binding in _bufferTextures) { var isStore = binding.BindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore); - var range = bufferCache.GetBufferRange(binding.Range, isStore); + var range = bufferCache.GetBufferRange(binding.Range, BufferStageUtils.TextureBuffer(binding.Stage, binding.BindingInfo.Flags), isStore); binding.Texture.SetStorage(range); // The texture must be rebound to use the new storage if it was updated. @@ -526,7 +526,7 @@ namespace Ryujinx.Graphics.Gpu.Memory foreach (var binding in _bufferTextureArrays) { - var range = bufferCache.GetBufferRange(binding.Range); + var range = bufferCache.GetBufferRange(binding.Range, BufferStage.None); binding.Texture.SetStorage(range); textureArray[0] = binding.Texture; @@ -536,7 +536,7 @@ namespace Ryujinx.Graphics.Gpu.Memory foreach (var binding in _bufferImageArrays) { var isStore = binding.BindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore); - var range = bufferCache.GetBufferRange(binding.Range, isStore); + var range = bufferCache.GetBufferRange(binding.Range, BufferStage.None, isStore); binding.Texture.SetStorage(range); textureArray[0] = binding.Texture; @@ -565,7 +565,7 @@ namespace Ryujinx.Graphics.Gpu.Memory if (!_indexBuffer.Range.IsUnmapped) { - BufferRange buffer = bufferCache.GetBufferRange(_indexBuffer.Range); + BufferRange buffer = bufferCache.GetBufferRange(_indexBuffer.Range, BufferStage.IndexBuffer); _context.Renderer.Pipeline.SetIndexBuffer(buffer, _indexBuffer.Type); } @@ -597,7 +597,7 @@ namespace Ryujinx.Graphics.Gpu.Memory continue; } - BufferRange buffer = bufferCache.GetBufferRange(vb.Range); + BufferRange buffer = bufferCache.GetBufferRange(vb.Range, BufferStage.VertexBuffer); vertexBuffers[index] = new VertexBufferDescriptor(buffer, vb.Stride, vb.Divisor); } @@ -637,7 +637,7 @@ namespace Ryujinx.Graphics.Gpu.Memory continue; } - tfbs[index] = bufferCache.GetBufferRange(tfb.Range, write: true); + tfbs[index] = bufferCache.GetBufferRange(tfb.Range, BufferStage.TransformFeedback, write: true); } _context.Renderer.Pipeline.SetTransformFeedbackBuffers(tfbs); @@ -684,7 +684,7 @@ namespace Ryujinx.Graphics.Gpu.Memory _context.SupportBufferUpdater.SetTfeOffset(index, tfeOffset); - buffers[index] = new BufferAssignment(index, bufferCache.GetBufferRange(range, write: true)); + buffers[index] = new BufferAssignment(index, bufferCache.GetBufferRange(range, BufferStage.TransformFeedback, write: true)); } } @@ -751,6 +751,7 @@ namespace Ryujinx.Graphics.Gpu.Memory for (ShaderStage stage = ShaderStage.Vertex; stage <= ShaderStage.Fragment; stage++) { ref var buffers = ref bindings[(int)stage - 1]; + BufferStage bufferStage = BufferStageUtils.FromShaderStage(stage); for (int index = 0; index < buffers.Count; index++) { @@ -762,8 +763,8 @@ namespace Ryujinx.Graphics.Gpu.Memory { var isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write); var range = isStorage - ? bufferCache.GetBufferRangeAligned(bounds.Range, isWrite) - : bufferCache.GetBufferRange(bounds.Range); + ? bufferCache.GetBufferRangeAligned(bounds.Range, bufferStage | BufferStageUtils.FromUsage(bounds.Flags), isWrite) + : bufferCache.GetBufferRange(bounds.Range, bufferStage); ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range); } @@ -799,8 +800,8 @@ namespace Ryujinx.Graphics.Gpu.Memory { var isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write); var range = isStorage - ? bufferCache.GetBufferRangeAligned(bounds.Range, isWrite) - : bufferCache.GetBufferRange(bounds.Range); + ? bufferCache.GetBufferRangeAligned(bounds.Range, BufferStageUtils.ComputeStorage(bounds.Flags), isWrite) + : bufferCache.GetBufferRange(bounds.Range, BufferStage.Compute); ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range); } @@ -875,7 +876,7 @@ namespace Ryujinx.Graphics.Gpu.Memory Format format, bool isImage) { - _channel.MemoryManager.Physical.BufferCache.CreateBuffer(range); + _channel.MemoryManager.Physical.BufferCache.CreateBuffer(range, BufferStageUtils.TextureBuffer(stage, bindingInfo.Flags)); _bufferTextures.Add(new BufferTextureBinding(stage, texture, range, bindingInfo, format, isImage)); } @@ -883,6 +884,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Sets the buffer storage of a buffer texture array element. This will be bound when the buffer manager commits bindings. /// + /// Shader stage accessing the texture /// Texture array where the element will be inserted /// Buffer texture /// Physical ranges of memory where the buffer texture data is located @@ -890,6 +892,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Index of the binding on the array /// Format of the buffer texture public void SetBufferTextureStorage( + ShaderStage stage, ITextureArray array, ITexture texture, MultiRange range, @@ -897,7 +900,7 @@ namespace Ryujinx.Graphics.Gpu.Memory int index, Format format) { - _channel.MemoryManager.Physical.BufferCache.CreateBuffer(range); + _channel.MemoryManager.Physical.BufferCache.CreateBuffer(range, BufferStageUtils.TextureBuffer(stage, bindingInfo.Flags)); _bufferTextureArrays.Add(new BufferTextureArrayBinding(array, texture, range, bindingInfo, index, format)); } @@ -905,6 +908,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Sets the buffer storage of a buffer image array element. This will be bound when the buffer manager commits bindings. /// + /// Shader stage accessing the texture /// Image array where the element will be inserted /// Buffer texture /// Physical ranges of memory where the buffer texture data is located @@ -912,6 +916,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Index of the binding on the array /// Format of the buffer texture public void SetBufferTextureStorage( + ShaderStage stage, IImageArray array, ITexture texture, MultiRange range, @@ -919,7 +924,7 @@ namespace Ryujinx.Graphics.Gpu.Memory int index, Format format) { - _channel.MemoryManager.Physical.BufferCache.CreateBuffer(range); + _channel.MemoryManager.Physical.BufferCache.CreateBuffer(range, BufferStageUtils.TextureBuffer(stage, bindingInfo.Flags)); _bufferImageArrays.Add(new BufferTextureArrayBinding(array, texture, range, bindingInfo, index, format)); } diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferMigration.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferMigration.cs index 0a52680316..ce99853188 100644 --- a/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferMigration.cs +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferMigration.cs @@ -1,37 +1,21 @@ using System; +using System.Threading; namespace Ryujinx.Graphics.Gpu.Memory { /// - /// A record of when buffer data was copied from one buffer to another, along with the SyncNumber when the migration will be complete. - /// Keeps the source buffer alive for data flushes until the migration is complete. + /// A record of when buffer data was copied from multiple buffers to one migration target, + /// along with the SyncNumber when the migration will be complete. + /// Keeps the source buffers alive for data flushes until the migration is complete. + /// All spans cover the full range of the "destination" buffer. /// internal class BufferMigration : IDisposable { /// - /// The offset for the migrated region. + /// Ranges from source buffers that were copied as part of this migration. + /// Ordered by increasing base address. /// - private readonly ulong _offset; - - /// - /// The size for the migrated region. - /// - private readonly ulong _size; - - /// - /// The buffer that was migrated from. - /// - private readonly Buffer _buffer; - - /// - /// The source range action, to be called on overlap with an unreached sync number. - /// - private readonly Action _sourceRangeAction; - - /// - /// The source range list. - /// - private readonly BufferModifiedRangeList _source; + public BufferMigrationSpan[] Spans { get; private set; } /// /// The destination range list. This range list must be updated when flushing the source. @@ -43,55 +27,193 @@ namespace Ryujinx.Graphics.Gpu.Memory /// public readonly ulong SyncNumber; + /// + /// Number of active users there are traversing this migration's spans. + /// + private int _refCount; + + /// + /// Create a new buffer migration. + /// + /// Source spans for the migration + /// Destination buffer range list + /// Sync number where this migration will be complete + public BufferMigration(BufferMigrationSpan[] spans, BufferModifiedRangeList destination, ulong syncNumber) + { + Spans = spans; + Destination = destination; + SyncNumber = syncNumber; + } + + /// + /// Add a span to the migration. Allocates a new array with the target size, and replaces it. + /// + /// + /// The base address for the span is assumed to be higher than all other spans in the migration, + /// to keep the span array ordered. + /// + public void AddSpanToEnd(BufferMigrationSpan span) + { + BufferMigrationSpan[] oldSpans = Spans; + + BufferMigrationSpan[] newSpans = new BufferMigrationSpan[oldSpans.Length + 1]; + + oldSpans.CopyTo(newSpans, 0); + + newSpans[oldSpans.Length] = span; + + Spans = newSpans; + } + + /// + /// Performs the given range action, or one from a migration that overlaps and has not synced yet. + /// + /// The offset to pass to the action + /// The size to pass to the action + /// The sync number that has been reached + /// The action to perform + public void RangeActionWithMigration(ulong offset, ulong size, ulong syncNumber, BufferFlushAction rangeAction) + { + long syncDiff = (long)(syncNumber - SyncNumber); + + if (syncDiff >= 0) + { + // The migration has completed. Run the parent action. + rangeAction(offset, size, syncNumber); + } + else + { + Interlocked.Increment(ref _refCount); + + ulong prevAddress = offset; + ulong endAddress = offset + size; + + foreach (BufferMigrationSpan span in Spans) + { + if (!span.Overlaps(offset, size)) + { + continue; + } + + if (span.Address > prevAddress) + { + // There's a gap between this span and the last (or the start address). Flush the range using the parent action. + + rangeAction(prevAddress, span.Address - prevAddress, syncNumber); + } + + span.RangeActionWithMigration(offset, size, syncNumber); + + prevAddress = span.Address + span.Size; + } + + if (endAddress > prevAddress) + { + // There's a gap at the end of the range with no migration. Flush the range using the parent action. + rangeAction(prevAddress, endAddress - prevAddress, syncNumber); + } + + Interlocked.Decrement(ref _refCount); + } + } + + /// + /// Dispose the buffer migration. This removes the reference from the destination range list, + /// and runs all the dispose buffers for the migration spans. (typically disposes the source buffer) + /// + public void Dispose() + { + while (Volatile.Read(ref _refCount) > 0) + { + // Coming into this method, the sync for the migration will be met, so nothing can increment the ref count. + // However, an existing traversal of the spans for data flush could still be in progress. + // Spin if this is ever the case, so they don't get disposed before the operation is complete. + } + + Destination.RemoveMigration(this); + + foreach (BufferMigrationSpan span in Spans) + { + span.Dispose(); + } + } + } + + /// + /// A record of when buffer data was copied from one buffer to another, for a specific range in a source buffer. + /// Keeps the source buffer alive for data flushes until the migration is complete. + /// + internal readonly struct BufferMigrationSpan : IDisposable + { + /// + /// The offset for the migrated region. + /// + public readonly ulong Address; + + /// + /// The size for the migrated region. + /// + public readonly ulong Size; + + /// + /// The action to perform when the migration isn't needed anymore. + /// + private readonly Action _disposeAction; + + /// + /// The source range action, to be called on overlap with an unreached sync number. + /// + private readonly BufferFlushAction _sourceRangeAction; + + /// + /// Optional migration for the source data. Can chain together if many migrations happen in a short time. + /// If this is null, then _sourceRangeAction will always provide up to date data. + /// + private readonly BufferMigration _source; + /// /// Creates a record for a buffer migration. /// /// The source buffer for this migration + /// The action to perform when the migration isn't needed anymore /// The flush action for the source buffer - /// The modified range list for the source buffer - /// The modified range list for the destination buffer - /// The sync number for when the migration is complete - public BufferMigration( + /// Pending migration for the source buffer + public BufferMigrationSpan( Buffer buffer, - Action sourceRangeAction, - BufferModifiedRangeList source, - BufferModifiedRangeList dest, - ulong syncNumber) + Action disposeAction, + BufferFlushAction sourceRangeAction, + BufferMigration source) { - _offset = buffer.Address; - _size = buffer.Size; - _buffer = buffer; + Address = buffer.Address; + Size = buffer.Size; + _disposeAction = disposeAction; _sourceRangeAction = sourceRangeAction; _source = source; - Destination = dest; - SyncNumber = syncNumber; } + /// + /// Creates a record for a buffer migration, using the default buffer dispose action. + /// + /// The source buffer for this migration + /// The flush action for the source buffer + /// Pending migration for the source buffer + public BufferMigrationSpan( + Buffer buffer, + BufferFlushAction sourceRangeAction, + BufferMigration source) : this(buffer, buffer.DecrementReferenceCount, sourceRangeAction, source) { } + /// /// Determine if the given range overlaps this migration, and has not been completed yet. /// /// Start offset /// Range size - /// The sync number that was waited on /// True if overlapping and in progress, false otherwise - public bool Overlaps(ulong offset, ulong size, ulong syncNumber) + public bool Overlaps(ulong offset, ulong size) { ulong end = offset + size; - ulong destEnd = _offset + _size; - long syncDiff = (long)(syncNumber - SyncNumber); // syncNumber is less if the copy has not completed. + ulong destEnd = Address + Size; - return !(end <= _offset || offset >= destEnd) && syncDiff < 0; - } - - /// - /// Determine if the given range matches this migration. - /// - /// Start offset - /// Range size - /// True if the range exactly matches, false otherwise - public bool FullyMatches(ulong offset, ulong size) - { - return _offset == offset && _size == size; + return !(end <= Address || offset >= destEnd); } /// @@ -100,26 +222,30 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Start offset /// Range size /// Current sync number - /// The modified range list that originally owned this range - public void RangeActionWithMigration(ulong offset, ulong size, ulong syncNumber, BufferModifiedRangeList parent) + public void RangeActionWithMigration(ulong offset, ulong size, ulong syncNumber) { ulong end = offset + size; - end = Math.Min(_offset + _size, end); - offset = Math.Max(_offset, offset); + end = Math.Min(Address + Size, end); + offset = Math.Max(Address, offset); size = end - offset; - _source.RangeActionWithMigration(offset, size, syncNumber, parent, _sourceRangeAction); + if (_source != null) + { + _source.RangeActionWithMigration(offset, size, syncNumber, _sourceRangeAction); + } + else + { + _sourceRangeAction(offset, size, syncNumber); + } } /// - /// Removes this reference to the range list, potentially allowing for the source buffer to be disposed. + /// Removes this migration span, potentially allowing for the source buffer to be disposed. /// public void Dispose() { - Destination.RemoveMigration(this); - - _buffer.DecrementReferenceCount(); + _disposeAction(); } } } diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs index 6ada8a4b25..d330de638a 100644 --- a/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs @@ -1,7 +1,6 @@ using Ryujinx.Common.Pools; using Ryujinx.Memory.Range; using System; -using System.Collections.Generic; using System.Linq; namespace Ryujinx.Graphics.Gpu.Memory @@ -72,10 +71,10 @@ namespace Ryujinx.Graphics.Gpu.Memory private readonly GpuContext _context; private readonly Buffer _parent; - private readonly Action _flushAction; + private readonly BufferFlushAction _flushAction; - private List _sources; - private BufferMigration _migrationTarget; + private BufferMigration _source; + private BufferModifiedRangeList _migrationTarget; private readonly object _lock = new(); @@ -99,7 +98,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// GPU context that the buffer range list belongs to /// The parent buffer that owns this range list /// The flush action for the parent buffer - public BufferModifiedRangeList(GpuContext context, Buffer parent, Action flushAction) : base(BackingInitialSize) + public BufferModifiedRangeList(GpuContext context, Buffer parent, BufferFlushAction flushAction) : base(BackingInitialSize) { _context = context; _parent = parent; @@ -199,6 +198,36 @@ namespace Ryujinx.Graphics.Gpu.Memory } } + /// + /// Gets modified ranges within the specified region, and then fires the given action for each range individually. + /// + /// Start address to query + /// Size to query + /// Sync number required for a range to be signalled + /// The action to call for each modified range + public void GetRangesAtSync(ulong address, ulong size, ulong syncNumber, Action rangeAction) + { + int count = 0; + + ref var overlaps = ref ThreadStaticArray.Get(); + + // Range list must be consistent for this operation. + lock (_lock) + { + count = FindOverlapsNonOverlapping(address, size, ref overlaps); + } + + for (int i = 0; i < count; i++) + { + BufferModifiedRange overlap = overlaps[i]; + + if (overlap.SyncNumber == syncNumber) + { + rangeAction(overlap.Address, overlap.Size); + } + } + } + /// /// Gets modified ranges within the specified region, and then fires the given action for each range individually. /// @@ -245,41 +274,16 @@ namespace Ryujinx.Graphics.Gpu.Memory /// The offset to pass to the action /// The size to pass to the action /// The sync number that has been reached - /// The modified range list that originally owned this range /// The action to perform - public void RangeActionWithMigration(ulong offset, ulong size, ulong syncNumber, BufferModifiedRangeList parent, Action rangeAction) + public void RangeActionWithMigration(ulong offset, ulong size, ulong syncNumber, BufferFlushAction rangeAction) { - bool firstSource = true; - - if (parent != this) + if (_source != null) { - lock (_lock) - { - if (_sources != null) - { - foreach (BufferMigration source in _sources) - { - if (source.Overlaps(offset, size, syncNumber)) - { - if (firstSource && !source.FullyMatches(offset, size)) - { - // Perform this buffer's action first. The migrations will run after. - rangeAction(offset, size); - } - - source.RangeActionWithMigration(offset, size, syncNumber, parent); - - firstSource = false; - } - } - } - } + _source.RangeActionWithMigration(offset, size, syncNumber, rangeAction); } - - if (firstSource) + else { - // No overlapping migrations, or they are not meant for this range, flush the data using the given action. - rangeAction(offset, size); + rangeAction(offset, size, syncNumber); } } @@ -319,7 +323,7 @@ namespace Ryujinx.Graphics.Gpu.Memory ClearPart(overlap, clampAddress, clampEnd); - RangeActionWithMigration(clampAddress, clampEnd - clampAddress, waitSync, overlap.Parent, _flushAction); + RangeActionWithMigration(clampAddress, clampEnd - clampAddress, waitSync, _flushAction); } } @@ -329,7 +333,7 @@ namespace Ryujinx.Graphics.Gpu.Memory // There is a migration target to call instead. This can't be changed after set so accessing it outside the lock is fine. - _migrationTarget.Destination.RemoveRangesAndFlush(overlaps, rangeCount, highestDiff, currentSync, address, endAddress); + _migrationTarget.RemoveRangesAndFlush(overlaps, rangeCount, highestDiff, currentSync, address, endAddress); } /// @@ -367,7 +371,7 @@ namespace Ryujinx.Graphics.Gpu.Memory if (rangeCount == -1) { - _migrationTarget.Destination.WaitForAndFlushRanges(address, size); + _migrationTarget.WaitForAndFlushRanges(address, size); return; } @@ -407,6 +411,9 @@ namespace Ryujinx.Graphics.Gpu.Memory /// /// Inherit ranges from another modified range list. /// + /// + /// Assumes that ranges will be inherited in address ascending order. + /// /// The range list to inherit from /// The action to call for each modified range public void InheritRanges(BufferModifiedRangeList ranges, Action registerRangeAction) @@ -415,18 +422,31 @@ namespace Ryujinx.Graphics.Gpu.Memory lock (ranges._lock) { - BufferMigration migration = new(ranges._parent, ranges._flushAction, ranges, this, _context.SyncNumber); - - ranges._parent.IncrementReferenceCount(); - ranges._migrationTarget = migration; - - _context.RegisterBufferMigration(migration); - inheritRanges = ranges.ToArray(); lock (_lock) { - (_sources ??= new List()).Add(migration); + // Copy over the migration from the previous range list + + BufferMigration oldMigration = ranges._source; + + BufferMigrationSpan span = new BufferMigrationSpan(ranges._parent, ranges._flushAction, oldMigration); + ranges._parent.IncrementReferenceCount(); + + if (_source == null) + { + // Create a new migration. + _source = new BufferMigration(new BufferMigrationSpan[] { span }, this, _context.SyncNumber); + + _context.RegisterBufferMigration(_source); + } + else + { + // Extend the migration + _source.AddSpanToEnd(span); + } + + ranges._migrationTarget = this; foreach (BufferModifiedRange range in inheritRanges) { @@ -445,6 +465,27 @@ namespace Ryujinx.Graphics.Gpu.Memory } } + /// + /// Register a migration from previous buffer storage. This migration is from a snapshot of the buffer's + /// current handle to its handle in the future, and is assumed to be complete when the sync action completes. + /// When the migration completes, the handle is disposed. + /// + public void SelfMigration() + { + lock (_lock) + { + BufferMigrationSpan span = new(_parent, _parent.GetSnapshotDisposeAction(), _parent.GetSnapshotFlushAction(), _source); + BufferMigration migration = new(new BufferMigrationSpan[] { span }, this, _context.SyncNumber); + + // Migration target is used to redirect flush actions to the latest range list, + // so we don't need to set it here. (this range list is still the latest) + + _context.RegisterBufferMigration(migration); + + _source = migration; + } + } + /// /// Removes a source buffer migration, indicating its copy has completed. /// @@ -453,7 +494,10 @@ namespace Ryujinx.Graphics.Gpu.Memory { lock (_lock) { - _sources.Remove(migration); + if (_source == migration) + { + _source = null; + } } } diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferPreFlush.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferPreFlush.cs new file mode 100644 index 0000000000..d58b9ea66d --- /dev/null +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferPreFlush.cs @@ -0,0 +1,295 @@ +using Ryujinx.Common; +using Ryujinx.Graphics.GAL; +using System; + +namespace Ryujinx.Graphics.Gpu.Memory +{ + /// + /// Manages flushing ranges from buffers in advance for easy access, if they are flushed often. + /// Typically, from device local memory to a host mapped target for cached access. + /// + internal class BufferPreFlush : IDisposable + { + private const ulong PageSize = MemoryManager.PageSize; + + /// + /// Threshold for the number of copies without a flush required to disable preflush on a page. + /// + private const int DeactivateCopyThreshold = 200; + + /// + /// Value that indicates whether a page has been flushed or copied before. + /// + private enum PreFlushState + { + None, + HasFlushed, + HasCopied + } + + /// + /// Flush state for each page of the buffer. + /// Controls whether data should be copied to the flush buffer, what sync is expected + /// and unflushed copy counting for stopping copies that are no longer needed. + /// + private struct PreFlushPage + { + public PreFlushState State; + public ulong FirstActivatedSync; + public ulong LastCopiedSync; + public int CopyCount; + } + + /// + /// True if there are ranges that should copy to the flush buffer, false otherwise. + /// + public bool ShouldCopy { get; private set; } + + private readonly GpuContext _context; + private readonly Buffer _buffer; + private readonly PreFlushPage[] _pages; + private readonly ulong _address; + private readonly ulong _size; + private readonly ulong _misalignment; + private readonly Action _flushAction; + + private BufferHandle _flushBuffer; + + public BufferPreFlush(GpuContext context, Buffer parent, Action flushAction) + { + _context = context; + _buffer = parent; + _address = parent.Address; + _size = parent.Size; + _pages = new PreFlushPage[BitUtils.DivRoundUp(_size, PageSize)]; + _misalignment = _address & (PageSize - 1); + + _flushAction = flushAction; + } + + /// + /// Ensure that the flush buffer exists. + /// + private void EnsureFlushBuffer() + { + if (_flushBuffer == BufferHandle.Null) + { + _flushBuffer = _context.Renderer.CreateBuffer((int)_size, BufferAccess.HostMemory); + } + } + + /// + /// Gets a page range from an address and size byte range. + /// + /// Range address + /// Range size + /// A page index and count + private (int index, int count) GetPageRange(ulong address, ulong size) + { + ulong offset = address - _address; + ulong endOffset = offset + size; + + int basePage = (int)(offset / PageSize); + int endPage = (int)((endOffset - 1) / PageSize); + + return (basePage, 1 + endPage - basePage); + } + + /// + /// Gets an offset and size range in the parent buffer from a page index and count. + /// + /// Range start page + /// Range page count + /// Offset and size range + private (int offset, int size) GetOffset(int startPage, int count) + { + int offset = (int)((ulong)startPage * PageSize - _misalignment); + int endOffset = (int)((ulong)(startPage + count) * PageSize - _misalignment); + + offset = Math.Max(0, offset); + endOffset = Math.Min((int)_size, endOffset); + + return (offset, endOffset - offset); + } + + /// + /// Copy a range of pages from the parent buffer into the flush buffer. + /// + /// Range start page + /// Range page count + private void CopyPageRange(int startPage, int count) + { + (int offset, int size) = GetOffset(startPage, count); + + EnsureFlushBuffer(); + + _context.Renderer.Pipeline.CopyBuffer(_buffer.Handle, _flushBuffer, offset, offset, size); + } + + /// + /// Copy a modified range into the flush buffer if it's marked as flushed. + /// Any pages the range overlaps are copied, and copies aren't repeated in the same sync number. + /// + /// Range address + /// Range size + public void CopyModified(ulong address, ulong size) + { + (int baseIndex, int count) = GetPageRange(address, size); + ulong syncNumber = _context.SyncNumber; + + int startPage = -1; + + for (int i = 0; i < count; i++) + { + int pageIndex = baseIndex + i; + ref PreFlushPage page = ref _pages[pageIndex]; + + if (page.State > PreFlushState.None) + { + // Perform the copy, and update the state of each page. + if (startPage == -1) + { + startPage = pageIndex; + } + + if (page.State != PreFlushState.HasCopied) + { + page.FirstActivatedSync = syncNumber; + page.State = PreFlushState.HasCopied; + } + else if (page.CopyCount++ >= DeactivateCopyThreshold) + { + page.CopyCount = 0; + page.State = PreFlushState.None; + } + + if (page.LastCopiedSync != syncNumber) + { + page.LastCopiedSync = syncNumber; + } + } + else if (startPage != -1) + { + CopyPageRange(startPage, pageIndex - startPage); + + startPage = -1; + } + } + + if (startPage != -1) + { + CopyPageRange(startPage, (baseIndex + count) - startPage); + } + } + + /// + /// Flush the given page range back into guest memory, optionally using data from the flush buffer. + /// The actual flushed range is an intersection of the page range and the address range. + /// + /// Address range start + /// Address range size + /// Page range start + /// Page range count + /// True if the data should come from the flush buffer + private void FlushPageRange(ulong address, ulong size, int startPage, int count, bool preFlush) + { + (int pageOffset, int pageSize) = GetOffset(startPage, count); + + int offset = (int)(address - _address); + int end = offset + (int)size; + + offset = Math.Max(offset, pageOffset); + end = Math.Min(end, pageOffset + pageSize); + + if (end >= offset) + { + BufferHandle handle = preFlush ? _flushBuffer : _buffer.Handle; + _flushAction(handle, _address + (ulong)offset, (ulong)(end - offset)); + } + } + + /// + /// Flush the given address range back into guest memory, optionally using data from the flush buffer. + /// When a copy has been performed on or before the waited sync number, the data can come from the flush buffer. + /// Otherwise, it flushes the parent buffer directly. + /// + /// Range address + /// Range size + /// Sync number that has been waited for + public void FlushWithAction(ulong address, ulong size, ulong syncNumber) + { + // Copy the parts of the range that have pre-flush copies that have been completed. + // Run the flush action for ranges that don't have pre-flush copies. + + // If a range doesn't have a pre-flush copy, consider adding one. + + (int baseIndex, int count) = GetPageRange(address, size); + + bool rangePreFlushed = false; + int startPage = -1; + + for (int i = 0; i < count; i++) + { + int pageIndex = baseIndex + i; + ref PreFlushPage page = ref _pages[pageIndex]; + + bool flushPage = false; + page.CopyCount = 0; + + if (page.State == PreFlushState.HasCopied) + { + if (syncNumber >= page.FirstActivatedSync) + { + // After the range is first activated, its data will always be copied to the preflush buffer on each sync. + flushPage = true; + } + } + else if (page.State == PreFlushState.None) + { + page.State = PreFlushState.HasFlushed; + ShouldCopy = true; + } + + if (flushPage) + { + if (!rangePreFlushed || startPage == -1) + { + if (startPage != -1) + { + FlushPageRange(address, size, startPage, pageIndex - startPage, false); + } + + rangePreFlushed = true; + startPage = pageIndex; + } + } + else if (rangePreFlushed || startPage == -1) + { + if (startPage != -1) + { + FlushPageRange(address, size, startPage, pageIndex - startPage, true); + } + + rangePreFlushed = false; + startPage = pageIndex; + } + } + + if (startPage != -1) + { + FlushPageRange(address, size, startPage, (baseIndex + count) - startPage, rangePreFlushed); + } + } + + /// + /// Dispose the flush buffer, if present. + /// + public void Dispose() + { + if (_flushBuffer != BufferHandle.Null) + { + _context.Renderer.DeleteBuffer(_flushBuffer); + } + } + } +} diff --git a/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs new file mode 100644 index 0000000000..d56abda284 --- /dev/null +++ b/ryujinx/src/Ryujinx.Graphics.Gpu/Memory/BufferStage.cs @@ -0,0 +1,99 @@ +using Ryujinx.Graphics.Shader; +using System.Runtime.CompilerServices; + +namespace Ryujinx.Graphics.Gpu.Memory +{ + /// + /// Pipeline stages that can modify buffer data, as well as flags indicating storage usage. + /// Must match ShaderStage for the shader stages, though anything after that can be in any order. + /// + internal enum BufferStage : byte + { + Compute, + Vertex, + TessellationControl, + TessellationEvaluation, + Geometry, + Fragment, + + Indirect, + VertexBuffer, + IndexBuffer, + Copy, + TransformFeedback, + Internal, + None, + + StageMask = 0x3f, + StorageMask = 0xc0, + + StorageRead = 0x40, + StorageWrite = 0x80, + +#pragma warning disable CA1069 // Enums values should not be duplicated + StorageAtomic = 0xc0 +#pragma warning restore CA1069 // Enums values should not be duplicated + } + + /// + /// Utility methods to convert shader stages and binding flags into buffer stages. + /// + internal static class BufferStageUtils + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static BufferStage FromShaderStage(ShaderStage stage) + { + return (BufferStage)stage; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static BufferStage FromShaderStage(int stageIndex) + { + return (BufferStage)(stageIndex + 1); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static BufferStage FromUsage(BufferUsageFlags flags) + { + if (flags.HasFlag(BufferUsageFlags.Write)) + { + return BufferStage.StorageWrite; + } + else + { + return BufferStage.StorageRead; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static BufferStage FromUsage(TextureUsageFlags flags) + { + if (flags.HasFlag(TextureUsageFlags.ImageStore)) + { + return BufferStage.StorageWrite; + } + else + { + return BufferStage.StorageRead; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static BufferStage TextureBuffer(ShaderStage shaderStage, TextureUsageFlags flags) + { + return FromShaderStage(shaderStage) | FromUsage(flags); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static BufferStage GraphicsStorage(int stageIndex, BufferUsageFlags flags) + { + return FromShaderStage(stageIndex) | FromUsage(flags); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static BufferStage ComputeStorage(BufferUsageFlags flags) + { + return BufferStage.Compute | FromUsage(flags); + } + } +} diff --git a/ryujinx/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs b/ryujinx/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs index 2a39ae446f..7bcff947e4 100644 --- a/ryujinx/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs +++ b/ryujinx/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs @@ -61,7 +61,9 @@ namespace Ryujinx.Graphics.OpenGL { BufferCount++; - if (access.HasFlag(GAL.BufferAccess.FlushPersistent)) + var memType = access & GAL.BufferAccess.MemoryTypeMask; + + if (memType == GAL.BufferAccess.HostMemory) { BufferHandle handle = Buffer.CreatePersistent(size); @@ -75,11 +77,6 @@ namespace Ryujinx.Graphics.OpenGL } } - public BufferHandle CreateBuffer(int size, GAL.BufferAccess access, BufferHandle storageHint) - { - return CreateBuffer(size, access); - } - public BufferHandle CreateBuffer(nint pointer, int size) { throw new NotSupportedException(); @@ -148,6 +145,7 @@ namespace Ryujinx.Graphics.OpenGL return new Capabilities( api: TargetApi.OpenGL, vendorName: GpuVendor, + memoryType: SystemMemoryType.BackendManaged, hasFrontFacingBug: intelWindows, hasVectorIndexingBug: amdWindows, needsFragmentOutputSpecialization: false, diff --git a/ryujinx/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs b/ryujinx/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs index 3673ee5a1f..3dcbc3130b 100644 --- a/ryujinx/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs +++ b/ryujinx/src/Ryujinx.Graphics.Vulkan/BufferHolder.cs @@ -1,4 +1,3 @@ -using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Silk.NET.Vulkan; using System; @@ -31,40 +30,29 @@ namespace Ryujinx.Graphics.Vulkan private readonly VulkanRenderer _gd; private readonly Device _device; - private MemoryAllocation _allocation; - private Auto _buffer; - private Auto _allocationAuto; + private readonly MemoryAllocation _allocation; + private readonly Auto _buffer; + private readonly Auto _allocationAuto; private readonly bool _allocationImported; - private ulong _bufferHandle; + private readonly ulong _bufferHandle; private CacheByRange _cachedConvertedBuffers; public int Size { get; } - private IntPtr _map; + private readonly IntPtr _map; - private MultiFenceHolder _waitable; + private readonly MultiFenceHolder _waitable; private bool _lastAccessIsWrite; - private BufferAllocationType _baseType; - private BufferAllocationType _currentType; - private bool _swapQueued; - - public BufferAllocationType DesiredType { get; private set; } - - private int _setCount; - private int _writeCount; - private int _flushCount; - private int _flushTemp; - private int _lastFlushWrite = -1; + private readonly BufferAllocationType _baseType; + private readonly BufferAllocationType _activeType; private readonly ReaderWriterLockSlim _flushLock; private FenceHolder _flushFence; private int _flushWaiting; - private List _swapActions; - private byte[] _pendingData; private BufferMirrorRangeList _pendingDataRanges; private Dictionary _mirrors; @@ -83,8 +71,7 @@ namespace Ryujinx.Graphics.Vulkan _map = allocation.HostPointer; _baseType = type; - _currentType = currentType; - DesiredType = currentType; + _activeType = currentType; _flushLock = new ReaderWriterLockSlim(); _useMirrors = gd.IsTBDR; @@ -104,8 +91,7 @@ namespace Ryujinx.Graphics.Vulkan _map = _allocation.HostPointer + offset; _baseType = type; - _currentType = currentType; - DesiredType = currentType; + _activeType = currentType; _flushLock = new ReaderWriterLockSlim(); } @@ -120,164 +106,11 @@ namespace Ryujinx.Graphics.Vulkan Size = size; _baseType = BufferAllocationType.Sparse; - _currentType = BufferAllocationType.Sparse; - DesiredType = BufferAllocationType.Sparse; + _activeType = BufferAllocationType.Sparse; _flushLock = new ReaderWriterLockSlim(); } - public bool TryBackingSwap(ref CommandBufferScoped? cbs) - { - if (_swapQueued && DesiredType != _currentType) - { - // Only swap if the buffer is not used in any queued command buffer. - bool isRented = _buffer.HasRentedCommandBufferDependency(_gd.CommandBufferPool); - - if (!isRented && _gd.CommandBufferPool.OwnedByCurrentThread && !_flushLock.IsReadLockHeld && (_pendingData == null || cbs != null)) - { - var currentAllocation = _allocationAuto; - var currentBuffer = _buffer; - IntPtr currentMap = _map; - - (VkBuffer buffer, MemoryAllocation allocation, BufferAllocationType resultType) = _gd.BufferManager.CreateBacking(_gd, Size, DesiredType, false, false, _currentType); - - if (buffer.Handle != 0) - { - if (cbs != null) - { - ClearMirrors(cbs.Value, 0, Size); - } - - _flushLock.EnterWriteLock(); - - ClearFlushFence(); - - _waitable = new MultiFenceHolder(Size); - - _allocation = allocation; - _allocationAuto = new Auto(allocation); - _buffer = new Auto(new DisposableBuffer(_gd.Api, _device, buffer), this, _waitable, _allocationAuto); - _bufferHandle = buffer.Handle; - _map = allocation.HostPointer; - - if (_map != IntPtr.Zero && currentMap != IntPtr.Zero) - { - // Copy data directly. Readbacks don't have to wait if this is done. - - unsafe - { - new Span((void*)currentMap, Size).CopyTo(new Span((void*)_map, Size)); - } - } - else - { - cbs ??= _gd.CommandBufferPool.Rent(); - - CommandBufferScoped cbsV = cbs.Value; - - Copy(_gd, cbsV, currentBuffer, _buffer, 0, 0, Size); - - // Need to wait for the data to reach the new buffer before data can be flushed. - - _flushFence = _gd.CommandBufferPool.GetFence(cbsV.CommandBufferIndex); - _flushFence.Get(); - } - - Logger.Debug?.PrintMsg(LogClass.Gpu, $"Converted {Size} buffer {_currentType} to {resultType}"); - - _currentType = resultType; - - if (_swapActions != null) - { - foreach (var action in _swapActions) - { - action(); - } - - _swapActions.Clear(); - } - - currentBuffer.Dispose(); - currentAllocation.Dispose(); - - _gd.PipelineInternal.SwapBuffer(currentBuffer, _buffer); - - _flushLock.ExitWriteLock(); - } - - _swapQueued = false; - - return true; - } - - return false; - } - - _swapQueued = false; - - return true; - } - - private void ConsiderBackingSwap() - { - if (_baseType == BufferAllocationType.Auto) - { - // When flushed, wait for a bit more info to make a decision. - bool wasFlushed = _flushTemp > 0; - int multiplier = wasFlushed ? 2 : 0; - if (_writeCount >= (WriteCountThreshold << multiplier) || _setCount >= (SetCountThreshold << multiplier) || _flushCount >= (FlushCountThreshold << multiplier)) - { - if (_flushCount > 0 || _flushTemp-- > 0) - { - // Buffers that flush should ideally be mapped in host address space for easy copies. - // If the buffer is large it will do better on GPU memory, as there will be more writes than data flushes (typically individual pages). - // If it is small, then it's likely most of the buffer will be flushed so we want it on host memory, as access is cached. - - bool hostMappingSensitive = _gd.Vendor == Vendor.Nvidia; - bool deviceLocalMapped = Size > DeviceLocalSizeThreshold || (wasFlushed && _writeCount > _flushCount * 10 && hostMappingSensitive) || _currentType == BufferAllocationType.DeviceLocalMapped; - - DesiredType = deviceLocalMapped ? BufferAllocationType.DeviceLocalMapped : BufferAllocationType.HostMapped; - - // It's harder for a buffer that is flushed to revert to another type of mapping. - if (_flushCount > 0) - { - _flushTemp = 1000; - } - } - else if (_writeCount >= (WriteCountThreshold << multiplier)) - { - // Buffers that are written often should ideally be in the device local heap. (Storage buffers) - DesiredType = BufferAllocationType.DeviceLocal; - } - else if (_setCount > (SetCountThreshold << multiplier)) - { - // Buffers that have their data set often should ideally be host mapped. (Constant buffers) - DesiredType = BufferAllocationType.HostMapped; - } - - _lastFlushWrite = -1; - _flushCount = 0; - _writeCount = 0; - _setCount = 0; - } - - if (!_swapQueued && DesiredType != _currentType) - { - _swapQueued = true; - - _gd.PipelineInternal.AddBackingSwap(this); - } - } - } - - public void Pin() - { - if (_baseType == BufferAllocationType.Auto) - { - _baseType = _currentType; - } - } - public unsafe Auto CreateView(VkFormat format, int offset, int size, Action invalidateView) { var bufferViewCreateInfo = new BufferViewCreateInfo @@ -291,19 +124,9 @@ namespace Ryujinx.Graphics.Vulkan _gd.Api.CreateBufferView(_device, bufferViewCreateInfo, null, out var bufferView).ThrowOnError(); - (_swapActions ??= new List()).Add(invalidateView); - return new Auto(new DisposableBufferView(_gd.Api, _device, bufferView), this, _waitable, _buffer); } - public void InheritMetrics(BufferHolder other) - { - _setCount = other._setCount; - _writeCount = other._writeCount; - _flushCount = other._flushCount; - _flushTemp = other._flushTemp; - } - public unsafe void InsertBarrier(CommandBuffer commandBuffer, bool isWrite) { // If the last access is write, we always need a barrier to be sure we will read or modify @@ -423,18 +246,8 @@ namespace Ryujinx.Graphics.Vulkan { if (isWrite) { - _writeCount++; - SignalWrite(0, Size); } - else if (isSSBO) - { - // Always consider SSBO access for swapping to device local memory. - - _writeCount++; - - ConsiderBackingSwap(); - } return _buffer; } @@ -443,8 +256,6 @@ namespace Ryujinx.Graphics.Vulkan { if (isWrite) { - _writeCount++; - SignalWrite(offset, size); } @@ -543,8 +354,6 @@ namespace Ryujinx.Graphics.Vulkan public void SignalWrite(int offset, int size) { - ConsiderBackingSwap(); - if (offset == 0 && size == Size) { _cachedConvertedBuffers.Clear(); @@ -624,13 +433,6 @@ namespace Ryujinx.Graphics.Vulkan WaitForFlushFence(); - if (_lastFlushWrite != _writeCount) - { - // If it's on the same page as the last flush, ignore it. - _lastFlushWrite = _writeCount; - _flushCount++; - } - Span result; if (_map != IntPtr.Zero) @@ -711,8 +513,7 @@ namespace Ryujinx.Graphics.Vulkan return; } - _setCount++; - bool allowMirror = _useMirrors && allowCbsWait && cbs != null && _currentType <= BufferAllocationType.HostMapped; + bool allowMirror = _useMirrors && allowCbsWait && cbs != null && _activeType <= BufferAllocationType.HostMapped; if (_map != IntPtr.Zero) { @@ -863,8 +664,6 @@ namespace Ryujinx.Graphics.Vulkan var dstBuffer = GetBuffer(cbs.CommandBuffer, dstOffset, data.Length, true).Get(cbs, dstOffset, data.Length, true).Value; - _writeCount--; - InsertBufferBarrier( _gd, cbs.CommandBuffer, @@ -1100,8 +899,6 @@ namespace Ryujinx.Graphics.Vulkan public void Dispose() { - _swapQueued = false; - _gd.PipelineInternal?.FlushCommandsIfWeightExceeding(_buffer, (ulong)Size); _buffer.Dispose(); diff --git a/ryujinx/src/Ryujinx.Graphics.Vulkan/BufferManager.cs b/ryujinx/src/Ryujinx.Graphics.Vulkan/BufferManager.cs index 33289a0e09..e73cde83c8 100644 --- a/ryujinx/src/Ryujinx.Graphics.Vulkan/BufferManager.cs +++ b/ryujinx/src/Ryujinx.Graphics.Vulkan/BufferManager.cs @@ -165,10 +165,6 @@ namespace Ryujinx.Graphics.Vulkan if (TryGetBuffer(range.Handle, out var existingHolder)) { - // Since this buffer now also owns the memory from the referenced buffer, - // we pin it to ensure the memory location will not change. - existingHolder.Pin(); - (var memory, var offset) = existingHolder.GetDeviceMemoryAndOffset(); memoryBinds[index] = new SparseMemoryBind() @@ -235,10 +231,9 @@ namespace Ryujinx.Graphics.Vulkan int size, bool sparseCompatible = false, BufferAllocationType baseType = BufferAllocationType.HostMapped, - BufferHandle storageHint = default, bool forceMirrors = false) { - return CreateWithHandle(gd, size, out _, sparseCompatible, baseType, storageHint, forceMirrors); + return CreateWithHandle(gd, size, out _, sparseCompatible, baseType, forceMirrors); } public BufferHandle CreateWithHandle( @@ -247,10 +242,9 @@ namespace Ryujinx.Graphics.Vulkan out BufferHolder holder, bool sparseCompatible = false, BufferAllocationType baseType = BufferAllocationType.HostMapped, - BufferHandle storageHint = default, bool forceMirrors = false) { - holder = Create(gd, size, forConditionalRendering: false, sparseCompatible, baseType, storageHint); + holder = Create(gd, size, forConditionalRendering: false, sparseCompatible, baseType); if (holder == null) { return BufferHandle.Null; @@ -387,31 +381,13 @@ namespace Ryujinx.Graphics.Vulkan int size, bool forConditionalRendering = false, bool sparseCompatible = false, - BufferAllocationType baseType = BufferAllocationType.HostMapped, - BufferHandle storageHint = default) + BufferAllocationType baseType = BufferAllocationType.HostMapped) { BufferAllocationType type = baseType; - BufferHolder storageHintHolder = null; if (baseType == BufferAllocationType.Auto) { - if (gd.IsSharedMemory) - { - baseType = BufferAllocationType.HostMapped; - type = baseType; - } - else - { - type = size >= BufferHolder.DeviceLocalSizeThreshold ? BufferAllocationType.DeviceLocal : BufferAllocationType.HostMapped; - } - - if (storageHint != BufferHandle.Null) - { - if (TryGetBuffer(storageHint, out storageHintHolder)) - { - type = storageHintHolder.DesiredType; - } - } + type = BufferAllocationType.HostMapped; } (VkBuffer buffer, MemoryAllocation allocation, BufferAllocationType resultType) = @@ -421,11 +397,6 @@ namespace Ryujinx.Graphics.Vulkan { var holder = new BufferHolder(gd, _device, buffer, allocation, size, baseType, resultType); - if (storageHintHolder != null) - { - holder.InheritMetrics(storageHintHolder); - } - return holder; } diff --git a/ryujinx/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs b/ryujinx/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs index f9243bf831..9d1fd9ffd3 100644 --- a/ryujinx/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs +++ b/ryujinx/src/Ryujinx.Graphics.Vulkan/EnumConversion.cs @@ -424,10 +424,20 @@ namespace Ryujinx.Graphics.Vulkan public static BufferAllocationType Convert(this BufferAccess access) { - if (access.HasFlag(BufferAccess.FlushPersistent) || access.HasFlag(BufferAccess.Stream)) + BufferAccess memType = access & BufferAccess.MemoryTypeMask; + + if (memType == BufferAccess.HostMemory || access.HasFlag(BufferAccess.Stream)) { return BufferAllocationType.HostMapped; } + else if (memType == BufferAccess.DeviceMemory) + { + return BufferAllocationType.DeviceLocal; + } + else if (memType == BufferAccess.DeviceMemoryMapped) + { + return BufferAllocationType.DeviceLocalMapped; + } return BufferAllocationType.Auto; } diff --git a/ryujinx/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs b/ryujinx/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs index 4987548cd8..357d517eb3 100644 --- a/ryujinx/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs +++ b/ryujinx/src/Ryujinx.Graphics.Vulkan/PipelineFull.cs @@ -222,20 +222,6 @@ namespace Ryujinx.Graphics.Vulkan } } - private void TryBackingSwaps() - { - CommandBufferScoped? cbs = null; - - _backingSwaps.RemoveAll(holder => holder.TryBackingSwap(ref cbs)); - - cbs?.Dispose(); - } - - public void AddBackingSwap(BufferHolder holder) - { - _backingSwaps.Add(holder); - } - public void Restore() { if (Pipeline != null) @@ -291,8 +277,6 @@ namespace Ryujinx.Graphics.Vulkan Gd.ResetCounterPool(); - TryBackingSwaps(); - Restore(); } diff --git a/ryujinx/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/ryujinx/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index 8ef05de36c..175d5e3ea3 100644 --- a/ryujinx/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/ryujinx/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -486,12 +486,7 @@ namespace Ryujinx.Graphics.Vulkan public BufferHandle CreateBuffer(int size, BufferAccess access) { - return BufferManager.CreateWithHandle(this, size, access.HasFlag(BufferAccess.SparseCompatible), access.Convert(), default, access == BufferAccess.Stream); - } - - public BufferHandle CreateBuffer(int size, BufferAccess access, BufferHandle storageHint) - { - return BufferManager.CreateWithHandle(this, size, access.HasFlag(BufferAccess.SparseCompatible), access.Convert(), storageHint); + return BufferManager.CreateWithHandle(this, size, access.HasFlag(BufferAccess.SparseCompatible), access.Convert(), access.HasFlag(BufferAccess.Stream)); } public BufferHandle CreateBuffer(nint pointer, int size) @@ -675,9 +670,23 @@ namespace Ryujinx.Graphics.Vulkan var limits = _physicalDevice.PhysicalDeviceProperties.Limits; var mainQueueProperties = _physicalDevice.QueueFamilyProperties[QueueFamilyIndex]; + SystemMemoryType memoryType; + + if (IsSharedMemory) + { + memoryType = SystemMemoryType.UnifiedMemory; + } + else + { + memoryType = Vendor == Vendor.Nvidia ? + SystemMemoryType.DedicatedMemorySlowStorage : + SystemMemoryType.DedicatedMemory; + } + return new Capabilities( api: TargetApi.Vulkan, GpuVendor, + memoryType: memoryType, hasFrontFacingBug: IsIntelWindows, hasVectorIndexingBug: Vendor == Vendor.Qualcomm, needsFragmentOutputSpecialization: IsMoltenVk, diff --git a/shadowsocks-rust/Cargo.lock b/shadowsocks-rust/Cargo.lock index d5f059bbb0..f9a29f979a 100644 --- a/shadowsocks-rust/Cargo.lock +++ b/shadowsocks-rust/Cargo.lock @@ -1716,9 +1716,9 @@ dependencies = [ [[package]] name = "libmimalloc-sys" -version = "0.1.37" +version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81eb4061c0582dedea1cbc7aff2240300dd6982e0239d1c99e65c1dbf4a30ba7" +checksum = "0e7bb23d733dfcc8af652a78b7bf232f0e967710d044732185e561e47c0336b6" dependencies = [ "cc", "libc", @@ -1853,9 +1853,9 @@ checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "mimalloc" -version = "0.1.41" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f41a2280ded0da56c8cf898babb86e8f10651a34adcfff190ae9a1159c6908d" +checksum = "e9186d86b79b52f4a77af65604b51225e8db1d6ee7e3f41aec1e40829c71a176" dependencies = [ "libmimalloc-sys", ] @@ -2377,9 +2377,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", "prost-derive", @@ -2408,9 +2408,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9554e3ab233f0a932403704f1a1d08c30d5ccd931adfdfa1e8b5a19b52c1d55a" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", "itertools", @@ -3419,9 +3419,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sysexits" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e933b3bce3eff11227656c623ffff3fd4de6d5410c3fc68de49ecca26bc2be" +checksum = "b5b86c78a4dc8f92a6c34c96eea37290389c40fe3ffe8a4dd9898cf8a1f14282" [[package]] name = "system-configuration" @@ -3483,18 +3483,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", diff --git a/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml b/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml index 70b1acaf12..15ec10534b 100644 --- a/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml +++ b/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml @@ -134,7 +134,7 @@ byte_string = "1.0" byteorder = "1.5" rand = { version = "0.8", features = ["small_rng"] } sled = { version = "0.34.7", features = ["compression"], optional = true } -prost = { version = "0.12.4", optional = true } +prost = { version = "0.12.6", optional = true } futures = "0.3" tokio = { version = "1.5", features = [ diff --git a/sing-box/docs/changelog.md b/sing-box/docs/changelog.md index 84e7f124a4..03e77a4ffa 100644 --- a/sing-box/docs/changelog.md +++ b/sing-box/docs/changelog.md @@ -2,9 +2,10 @@ icon: material/alert-decagram --- -#### 1.9.0-rc.19 +#### 1.9.0-rc.20 -* Fixes and improvements +* Prioritize `*_route_address` in linux auto-route +* Fix `*_route_address` in darwin auto-route #### 1.8.14 diff --git a/sing-box/go.mod b/sing-box/go.mod index ba524552fe..2d2ac21785 100644 --- a/sing-box/go.mod +++ b/sing-box/go.mod @@ -33,7 +33,7 @@ require ( github.com/sagernet/sing-shadowsocks v0.2.6 github.com/sagernet/sing-shadowsocks2 v0.2.0 github.com/sagernet/sing-shadowtls v0.1.4 - github.com/sagernet/sing-tun v0.3.0-beta.2 + github.com/sagernet/sing-tun v0.3.0-beta.5 github.com/sagernet/sing-vmess v0.1.8 github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6 diff --git a/sing-box/go.sum b/sing-box/go.sum index 74fd8ef5df..6ee22b69b1 100644 --- a/sing-box/go.sum +++ b/sing-box/go.sum @@ -120,8 +120,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wK github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k= github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4= -github.com/sagernet/sing-tun v0.3.0-beta.2 h1:sfeHWnBTKGpFUjXpT+O/JEwFP8oVAo3M0Xx94ghesjU= -github.com/sagernet/sing-tun v0.3.0-beta.2/go.mod h1:xPaOkQhngPMILx+/9DMLCFl4vSxUU2tMnCPSlf05HLo= +github.com/sagernet/sing-tun v0.3.0-beta.5 h1:z+4l1mGjPeepxT3mzHzE2pms995iUac/AyKQvRnWbWA= +github.com/sagernet/sing-tun v0.3.0-beta.5/go.mod h1:xPaOkQhngPMILx+/9DMLCFl4vSxUU2tMnCPSlf05HLo= github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc= github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= diff --git a/small/luci-app-ssr-plus/po/zh-cn/ssr-plus.po b/small/luci-app-ssr-plus/po/zh-cn/ssr-plus.po index 7d9f13bfa7..e292f10261 100644 --- a/small/luci-app-ssr-plus/po/zh-cn/ssr-plus.po +++ b/small/luci-app-ssr-plus/po/zh-cn/ssr-plus.po @@ -155,22 +155,22 @@ msgid "Obfuscation Password" msgstr "混淆密码" msgid "Hysterir QUIC parameters" -msgstr "QUIC参数" +msgstr "QUIC 参数" msgid "QUIC initStreamReceiveWindow" -msgstr "QUIC初始流接收窗口大小。" +msgstr "QUIC 初始流接收窗口大小。" msgid "QUIC maxStreamReceiveWindow" -msgstr "QUIC最大的流接收窗口大小" +msgstr "QUIC 最大的流接收窗口大小" msgid "QUIC initConnReceiveWindow" -msgstr "QUIC初始的连接接收窗口大小" +msgstr "QUIC 初始的连接接收窗口大小" msgid "QUIC maxConnReceiveWindow" -msgstr "QUIC最大的连接接收窗口大小" +msgstr "QUIC 最大的连接接收窗口大小" msgid "QUIC maxIdleTimeout(Unit:second)" -msgstr "QUIC最长空闲超时时间(单位:秒)" +msgstr "QUIC 最长空闲超时时间(单位:秒)" msgid "The keep-alive period.(Unit:second)" msgstr "心跳包发送间隔(单位:秒)" @@ -195,7 +195,7 @@ msgid "Shadow-TLS ChainPoxy type" msgstr "代理链类型" msgid "Shadowsocks-rust Version" -msgstr "shadowsocks rust版本" +msgstr "shadowsocks rust 版本" msgid "Vmess Protocol" msgstr "VMESS协议" @@ -1003,19 +1003,19 @@ msgid "Enable Netflix Mode" msgstr "启用 Netflix 分流模式" msgid "TUIC User UUID" -msgstr "TUIC用户uuid" +msgstr "TUIC 用户 uuid" msgid "TUIC Server IP Address" -msgstr "TUIC 服务器IP地址" +msgstr "TUIC 服务器 IP 地址" msgid "TUIC User Password" -msgstr "TUIC用户密钥" +msgstr "TUIC 用户密钥" msgid "UDP relay mode" -msgstr "UDP中继模式" +msgstr "UDP 中继模式" msgid "native UDP characteristics" -msgstr "原生UDP特性" +msgstr "原生 UDP 特性" msgid "lossless UDP relay using QUIC streams" msgstr "使用 QUIC 流的无损 UDP 中继" @@ -1030,13 +1030,13 @@ msgid "Timeout for establishing a connection to server(second)" msgstr "连接超时时间(单位:秒)" msgid "Garbage collection interval(second)" -msgstr "UDP数据包片残片清理间隔(单位:秒)" +msgstr "UDP 数据包片残片清理间隔(单位:秒)" msgid "Garbage collection lifetime(second)" -msgstr "UDP数据包残片在服务器的保留时间(单位:秒)" +msgstr "UDP 数据包残片在服务器的保留时间(单位:秒)" msgid "Disable SNI" -msgstr "关闭SNI服务器名称指示" +msgstr "关闭 SNI 服务器名称指示" msgid "Enable 0-RTT QUIC handshake" msgstr "客户端启用 0-RTT QUIC 连接握手" @@ -1048,13 +1048,13 @@ msgid "TUIC receive window" msgstr "接收窗口(无需确认即可接收的最大字节数:默认8Mb)" msgid "Dual-stack Listening Socket" -msgstr "双栈Socket监听" +msgstr "双栈 Socket 监听" msgid "If this option is not set, the socket behavior is platform dependent." -msgstr "如果未设置此选项,则套接字行为依赖于平台。" +msgstr "如果未设置此选项,则 Socket 行为依赖于平台。" msgid "Maximum packet size the socks5 server can receive from external" -msgstr "socks5服务器可以从外部接收的最大数据包大小(单位:字节)" +msgstr "socks5 服务器可以从外部接收的最大数据包大小(单位:字节)" msgid "Disable ChinaDNS-NG" -msgstr "直通模式(禁用ChinaDNS-NG)" +msgstr "直通模式(禁用 ChinaDNS-NG)" diff --git a/small/sing-box/Makefile b/small/sing-box/Makefile index c7c7e29783..d43553705b 100644 --- a/small/sing-box/Makefile +++ b/small/sing-box/Makefile @@ -6,12 +6,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=sing-box -PKG_VERSION:=1.8.13 +PKG_VERSION:=1.8.14 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/SagerNet/sing-box/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=de1c09d096c6fca9f59863a051438aeb3197713faa6518cb46d7ca0a9bc63976 +PKG_HASH:=2ba7cfa097f5963ba304d47606e7a6b61bf881eb86cbed78fa6e4efae44a0a5f PKG_LICENSE:=GPL-3.0-or-later PKG_LICENSE_FILES:=LICENSE diff --git a/small/v2ray-geodata/Makefile b/small/v2ray-geodata/Makefile index 584e190b1d..1f372612c1 100644 --- a/small/v2ray-geodata/Makefile +++ b/small/v2ray-geodata/Makefile @@ -30,13 +30,13 @@ define Download/geosite HASH:=25d6120b009498ac83ae723e9751a19ff545fac4800dad53ab6e2592c3407533 endef -GEOSITE_IRAN_VER:=202405130027 +GEOSITE_IRAN_VER:=202405200027 GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER) define Download/geosite-ir URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/ URL_FILE:=iran.dat FILE:=$(GEOSITE_IRAN_FILE) - HASH:=a20aace2fb0e7a2a90bf8b18f7ce01478244f545a419ebc515f94f129bcd2085 + HASH:=19b8a3aa46f5ce3543f9e3ebe64ad3437ce02189ba67be4d7931d7babdf42a84 endef define Package/v2ray-geodata/template diff --git a/suyu/CONTRIBUTING.md b/suyu/CONTRIBUTING.md index b2bb3f0c76..1ff49d5b1f 100644 --- a/suyu/CONTRIBUTING.md +++ b/suyu/CONTRIBUTING.md @@ -6,5 +6,5 @@ SPDX-License-Identifier: GPL-2.0-or-later Please check out the - * [Contributors's guide](https://gitlab.com/suyu-emu/suyu/-/wikis/Contributing). - * [Merge request guidelines](https://gitlab.com/suyu-emu/suyu/-/wikis/Merge-requests) + * [Contributors's guide](https://git.suyu.dev/suyu/suyu/wiki/Contributing). + * [Merge request guidelines](https://git.suyu.dev/suyu/suyu/wiki/Typical-Git-Workflow#once-your-pull-request-is-ready-to-be-merged) diff --git a/suyu/MIGRATION.md b/suyu/MIGRATION.md new file mode 100644 index 0000000000..425e301136 --- /dev/null +++ b/suyu/MIGRATION.md @@ -0,0 +1,21 @@ +# Migrating from yuzu + +When coming from yuzu, the migration is as easy as renaming some directories. + +## Windows + +Use the run dialog to go to `%APPDATA%` or manually go to `C:\Users\{USERNAME}\AppData\Roaming` (you may have to enable hidden files) and simply rename the `yuzu` directories and simply rename those to `suyu`. + +## Unix (macOS/Linux) +Similarly, you can simply rename the folders `~/.local/share/yuzu` and `~/.config/yuzu` to `suyu`, either via a file manager or with the following commands: +```sh + $ mv ~/.local/share/yuzu ~/.local/share/suyu + $ mv ~/.config/yuzu ~/.config/suyu +``` +There is also `~/.cache/yuzu`, which you can safely delete. Suyu will build a fresh cache in its own directory. + +### Linux +Depending on your setup, you may want to substitute those base paths for `$XDG_DATA_HOME` and `$XDG_CONFIG_HOME` respectively. + +## Android +TBD \ No newline at end of file diff --git a/suyu/README.md b/suyu/README.md index 54274fa083..a423a83169 100644 --- a/suyu/README.md +++ b/suyu/README.md @@ -9,7 +9,7 @@ SPDX-License-Identifier: GPL-3.0-or-later We're in need of developers. Please join our chat below if you want to contribute! This repo was based on Yuzu EA 4176 but the code is being rewritten from the ground up for legal and performance reasons. -Support the original suyu developer team [here](https://discord.gg/ajz5hdrZ) +Support the original suyu developer team [here](https://discord.gg/79B6wqFPnc).
@@ -23,7 +23,7 @@ Support the original suyu developer team [here](https://discord.gg/ajz5hdrZ)

suyu was the continuation of the world's most popular, open-source Nintendo Switch emulator, yuzu, but is now something more.
-It is written in C++ (C# possibly required soon) with portability in mind, we actively work on builds for Windows, Linux, Android and hopefully IOS, along with a WIP custom OS called suyuOS (https://git.suyu.dev/suyu/suyu-os) . +It is written in C++ with portability in mind, and we actively provide builds for Windows, Linux, Android and iOS potentially coming soon.

@@ -41,6 +41,10 @@ It is written in C++ (C# possibly required soon) with portability in mind, we ac ## Hardware Requirements [Click here to see the Hardware Requirements](https://git.suyu.dev/suyu/suyu/wiki/Hardware-Requirements) +## Migrating from yuzu + +See [MIGRATION.md](MIGRATION.md). + ## Status We currently have builds over at the [Releases](https://git.suyu.dev/suyu/suyu/releases) page. @@ -51,10 +55,10 @@ We currently have builds over at the [Releases](https://git.suyu.dev/suyu/suyu/r This project is completely free and open source, and anyone can contribute to help improve suyu. -Most of the development happens on GitLab. For development discussion, please join us in our [Chat](https://chat.suyu.dev). +Most of the development happens on the Git. For development discussion, please join us in our [Chat](https://chat.suyu.dev) or contact a developer. If you want to contribute, please take a look at the [Contributor's Guide](https://git.suyu.dev/suyu/suyu/wiki/Contributing) and [Developer Information](https://git.suyu.dev/suyu/suyu/wiki/Developer-Information). -You can also contact any of the developers on Discord to learn more about the current state of suyu. +You can also contact any of the developers on the Chat to learn more about the current state of suyu. ## Downloads @@ -62,13 +66,12 @@ You can also contact any of the developers on Discord to learn more about the cu * __Linux__: [Releases](https://git.suyu.dev/suyu/suyu/releases) * __macOS__: [Releases](https://git.suyu.dev/suyu/suyu/releases) * __Android__: [Releases](https://git.suyu.dev/suyu/suyu/releases) -* __For IOS users, we recommend Sudachi__: [Releases](https://github.com/emuPlace/Sudachi/releases) +###### We currently do not provide builds for iOS, however if you would like, you could try the experimental [Sudachi](https://github.com/emuPlace/Sudachi/releases)/[Folium](https://github.com/jarrodnorwell/Folium/releases). -If you want daily builds then [Click here](https://git.suyu.dev/suyu/suyu/actions) +If you want daily builds then [Click here](https://git.suyu.dev/suyu/suyu/actions). If you don't know how to download the daily builds then [Click here](https://git.suyu.dev/suyu/suyu/raw/branch/dev/img/daily-builds.png) -Right now we only have daily builds for Linux and Android. -We have official builds [here.](https://git.suyu.dev/suyu/suyu/releases) If any website or person is claiming to have a build for suyu, take that with a grain of salt. +We have official builds [here.](https://git.suyu.dev/suyu/suyu/releases)
If any website or person is claiming to have a build for suyu, take that with a grain of salt. ## Building @@ -81,7 +84,7 @@ We have official builds [here.](https://git.suyu.dev/suyu/suyu/releases) If any ## Support -If you have any questions, don't hesitate to ask us in our [chat](https://chat.suyu.dev). We don't bite! +If you have any questions, don't hesitate to ask us in our [chat](https://chat.suyu.dev), make an issue or contact a developer. We don't bite! ## License diff --git a/v2rayng/V2rayNG/app/src/main/res/anim/fade_in.xml b/v2rayng/V2rayNG/app/src/main/res/anim/fade_in.xml deleted file mode 100644 index 29e04320a1..0000000000 --- a/v2rayng/V2rayNG/app/src/main/res/anim/fade_in.xml +++ /dev/null @@ -1,6 +0,0 @@ - - diff --git a/v2rayng/V2rayNG/app/src/main/res/anim/fade_out.xml b/v2rayng/V2rayNG/app/src/main/res/anim/fade_out.xml deleted file mode 100644 index 2b8bb1cb1f..0000000000 --- a/v2rayng/V2rayNG/app/src/main/res/anim/fade_out.xml +++ /dev/null @@ -1,6 +0,0 @@ - - diff --git a/v2rayng/V2rayNG/app/src/main/res/drawable-hdpi/ic_stat_name_black.png b/v2rayng/V2rayNG/app/src/main/res/drawable-hdpi/ic_stat_name_black.png deleted file mode 100644 index 5361ddf6cd..0000000000 Binary files a/v2rayng/V2rayNG/app/src/main/res/drawable-hdpi/ic_stat_name_black.png and /dev/null differ diff --git a/v2rayng/V2rayNG/app/src/main/res/drawable/ic_attach_money_24dp.xml b/v2rayng/V2rayNG/app/src/main/res/drawable/ic_attach_money_24dp.xml deleted file mode 100644 index b520fc98d0..0000000000 --- a/v2rayng/V2rayNG/app/src/main/res/drawable/ic_attach_money_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/v2rayng/V2rayNG/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/v2rayng/V2rayNG/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 76cd64629a..0000000000 Binary files a/v2rayng/V2rayNG/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/v2rayng/V2rayNG/app/src/main/res/values-sw360dp-v13/values-preference.xml b/v2rayng/V2rayNG/app/src/main/res/values-sw360dp-v13/values-preference.xml index 9915362428..692929d64b 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-sw360dp-v13/values-preference.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-sw360dp-v13/values-preference.xml @@ -1,5 +1,2 @@ - - false - 0dp - \ No newline at end of file + \ No newline at end of file diff --git a/xray-core/go.mod b/xray-core/go.mod index 269d02ad87..e265794a24 100644 --- a/xray-core/go.mod +++ b/xray-core/go.mod @@ -12,7 +12,7 @@ require ( github.com/miekg/dns v1.1.59 github.com/pelletier/go-toml v1.9.5 github.com/pires/go-proxyproto v0.7.0 - github.com/quic-go/quic-go v0.43.1 + github.com/quic-go/quic-go v0.44.0 github.com/refraction-networking/utls v1.6.6 github.com/sagernet/sing v0.3.8 github.com/sagernet/sing-shadowsocks v0.2.6 @@ -49,11 +49,11 @@ require ( github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/vishvananda/netns v0.0.4 // indirect go.uber.org/mock v0.4.0 // indirect - golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect - golang.org/x/mod v0.16.0 // indirect + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect + golang.org/x/mod v0.17.0 // indirect golang.org/x/text v0.15.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.19.0 // indirect + golang.org/x/tools v0.21.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/xray-core/go.sum b/xray-core/go.sum index 8a53ac247c..3db3444a41 100644 --- a/xray-core/go.sum +++ b/xray-core/go.sum @@ -114,8 +114,8 @@ github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/quic-go/quic-go v0.43.1 h1:fLiMNfQVe9q2JvSsiXo4fXOEguXHGGl9+6gLp4RPeZQ= -github.com/quic-go/quic-go v0.43.1/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M= +github.com/quic-go/quic-go v0.44.0 h1:So5wOr7jyO4vzL2sd8/pD9Kesciv91zSk8BoFngItQ0= +github.com/quic-go/quic-go v0.44.0/go.mod h1:z4cx/9Ny9UtGITIPzmPTXh1ULfOyWh4qGQlpnPcWmek= github.com/refraction-networking/utls v1.6.6 h1:igFsYBUJPYM8Rno9xUuDoM5GQrVEqY4llzEXOkL43Ig= github.com/refraction-networking/utls v1.6.6/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= @@ -184,14 +184,14 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= +golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= -golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -250,8 +250,8 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= -golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= +golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= +golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/xray-core/proxy/freedom/freedom.go b/xray-core/proxy/freedom/freedom.go index 9e6afc9d1a..29621c0ec8 100644 --- a/xray-core/proxy/freedom/freedom.go +++ b/xray-core/proxy/freedom/freedom.go @@ -219,10 +219,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte defer timer.SetTimeout(plcy.Timeouts.UplinkOnly) if destination.Network == net.Network_TCP { var writeConn net.Conn + var inTimer *signal.ActivityTimer if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil && useSplice { writeConn = inbound.Conn + inTimer = inbound.Timer } - return proxy.CopyRawConnIfExist(ctx, conn, writeConn, link.Writer, timer) + return proxy.CopyRawConnIfExist(ctx, conn, writeConn, link.Writer, timer, inTimer) } reader := NewPacketReader(conn, UDPOverride) if err := buf.Copy(reader, output, buf.UpdateActivity(timer)); err != nil { diff --git a/xray-core/proxy/proxy.go b/xray-core/proxy/proxy.go index ba909197a6..db92051074 100644 --- a/xray-core/proxy/proxy.go +++ b/xray-core/proxy/proxy.go @@ -470,7 +470,7 @@ func UnwrapRawConn(conn net.Conn) (net.Conn, stats.Counter, stats.Counter) { // CopyRawConnIfExist use the most efficient copy method. // - If caller don't want to turn on splice, do not pass in both reader conn and writer conn // - writer are from *transport.Link -func CopyRawConnIfExist(ctx context.Context, readerConn net.Conn, writerConn net.Conn, writer buf.Writer, timer *signal.ActivityTimer) error { +func CopyRawConnIfExist(ctx context.Context, readerConn net.Conn, writerConn net.Conn, writer buf.Writer, timer *signal.ActivityTimer, inTimer *signal.ActivityTimer) error { readerConn, readCounter, _ := UnwrapRawConn(readerConn) writerConn, _, writeCounter := UnwrapRawConn(writerConn) reader := buf.NewReader(readerConn) @@ -510,6 +510,9 @@ func CopyRawConnIfExist(ctx context.Context, readerConn net.Conn, writerConn net //runtime.Gosched() // necessary time.Sleep(time.Millisecond) // without this, there will be a rare ssl error for freedom splice timer.SetTimeout(8 * time.Hour) // prevent leak, just in case + if inTimer != nil { + inTimer.SetTimeout(8 * time.Hour) + } w, err := tc.ReadFrom(readerConn) if readCounter != nil { readCounter.Add(w) // outbound stats diff --git a/xray-core/proxy/vless/encoding/encoding.go b/xray-core/proxy/vless/encoding/encoding.go index cb55858489..5954746eac 100644 --- a/xray-core/proxy/vless/encoding/encoding.go +++ b/xray-core/proxy/vless/encoding/encoding.go @@ -179,8 +179,10 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer, for { if trafficState.ReaderSwitchToDirectCopy { var writerConn net.Conn + var inTimer *signal.ActivityTimer if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil { writerConn = inbound.Conn + inTimer = inbound.Timer if inbound.CanSpliceCopy == 2 { inbound.CanSpliceCopy = 1 } @@ -188,7 +190,7 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer, ob.CanSpliceCopy = 1 } } - return proxy.CopyRawConnIfExist(ctx, conn, writerConn, writer, timer) + return proxy.CopyRawConnIfExist(ctx, conn, writerConn, writer, timer, inTimer) } buffer, err := reader.ReadMultiBuffer() if !buffer.IsEmpty() { diff --git a/xray-core/proxy/vless/inbound/inbound.go b/xray-core/proxy/vless/inbound/inbound.go index d44b8c0943..1b31751c48 100644 --- a/xray-core/proxy/vless/inbound/inbound.go +++ b/xray-core/proxy/vless/inbound/inbound.go @@ -502,6 +502,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s sessionPolicy = h.policyManager.ForLevel(request.User.Level) ctx, cancel := context.WithCancel(ctx) timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) + inbound.Timer = timer ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer) link, err := dispatcher.Dispatch(ctx, request.Destination()) diff --git a/yass/.github/workflows/releases-deb.yml b/yass/.github/workflows/releases-deb.yml index 414f2c8cf3..6b7b3bae08 100644 --- a/yass/.github/workflows/releases-deb.yml +++ b/yass/.github/workflows/releases-deb.yml @@ -52,9 +52,9 @@ jobs: - distro: sid arch: riscv64 # XFAIL stretch - # XFAIL focal-i386,jammy-i386 + # XFAIL focal-i386,jammy-i386,noble-i386 # XFAIL sid-riscv64 (gui, curl) - # distro: [trusty, xenial, bionic, focal, jammy, stretch, buster, bullseye, bookworm] + # distro: [trusty, xenial, bionic, focal, jammy, noble, stretch, buster, bullseye, bookworm] # arch: [i386, amd64, armhf, arm64] # include: # - distro: stretch @@ -104,16 +104,16 @@ jobs: run: | sudo sed -i 's/azure.archive.ubuntu.com/azure.archive.ubuntu.com/g' /etc/apt/sources.list sudo apt-get update -qq - - name: Populate depedencies (debian keyring, for debian distributions) + - name: Populate dependencies (debian keyring, for debian distributions) run: | curl -O http://ftp.us.debian.org/debian/pool/main/d/debian-archive-keyring/debian-archive-keyring_2023.4_all.deb sudo apt-get update -qq && sudo apt-get install -f -y $PWD/debian*.deb rm -f *.deb - - name: Populate depedencies (sbuild, debhelper, schroot, debootstrap and ubuntu-dev-tools) + - name: Populate dependencies (sbuild, debhelper, schroot, debootstrap and ubuntu-dev-tools) run: | sudo apt-get update -qq sudo apt-get install -y sbuild debhelper schroot debootstrap ubuntu-dev-tools qemu-user-static - - name: Populate depedencies (deboostrap update for sid fix) + - name: Populate dependencies (deboostrap update for sid fix) if: ${{ env.HOST_DISTRO == 'sid' }} run: | curl -L -O http://mirrors.kernel.org/ubuntu/pool/main/d/debootstrap/debootstrap_1.0.132ubuntu1_all.deb @@ -229,12 +229,12 @@ jobs: sudo schroot --chroot "source:${{ env.HOST_DISTRO }}-${{ env.BUILD_ARCH }}-${{ env.HOST_ARCH }}" --user root -- \ apt-get install -y ca-certificates git - name: Populate sysroot (golang, new distro) - if: ${{ steps.schroot-cache.outputs.cache-hit != 'true' && (env.HOST_DISTRO == 'focal' || env.HOST_DISTRO == 'jammy' || env.HOST_DISTRO == 'bookworm' || env.HOST_DISTRO == 'sid') }} + if: ${{ steps.schroot-cache.outputs.cache-hit != 'true' && env.HOST_DISTRO != 'trusty' && env.HOST_DISTRO != 'xenial' && env.HOST_DISTRO != 'bionic' && env.HOST_DISTRO != 'stretch' && env.HOST_DISTRO != 'buster' && env.HOST_DISTRO != 'bullseye' }} run: | sudo schroot --chroot "source:${{ env.HOST_DISTRO }}-${{ env.BUILD_ARCH }}-${{ env.HOST_ARCH }}" --user root -- \ apt-get install -y golang - name: Populate sysroot (golang, old distro) - if: ${{ steps.schroot-cache.outputs.cache-hit != 'true' && env.HOST_DISTRO != 'focal' && env.HOST_DISTRO != 'jammy' && env.HOST_DISTRO != 'bookworm' && env.HOST_DISTRO != 'sid' }} + if: ${{ steps.schroot-cache.outputs.cache-hit != 'true' && (env.HOST_DISTRO == 'trusty' || env.HOST_DISTRO == 'xenial' || env.HOST_DISTRO == 'bionic' || env.HOST_DISTRO == 'stretch' || env.HOST_DISTRO == 'buster' || env.HOST_DISTRO == 'bullseye') }} run: | # shipped with debian bullseye curl -O http://ftp.us.debian.org/debian/pool/main/g/golang-defaults/golang_1.15~1_${{ env.BUILD_ARCH }}.deb @@ -250,40 +250,41 @@ jobs: sudo schroot --chroot "source:${{ env.HOST_DISTRO }}-${{ env.BUILD_ARCH }}-${{ env.HOST_ARCH }}" --user root -- \ apt-get install -y -f rm -f *.deb - - name: Populate depedencie (cmake, new distro) - if: ${{ steps.schroot-cache.outputs.cache-hit != 'true' && (env.HOST_DISTRO == 'focal' || env.HOST_DISTRO == 'jammy' || env.HOST_DISTRO == 'bookworm' || env.HOST_DISTRO == 'sid') }} + - name: Populate dependencie (cmake) + if: ${{ steps.schroot-cache.outputs.cache-hit != 'true' }} run: | sudo schroot --chroot "source:${{ env.HOST_DISTRO }}-${{ env.BUILD_ARCH }}-${{ env.HOST_ARCH }}" --user root -- \ - apt-get install -y cmake - - name: Populate depedencie (cmake, old distro) - if: ${{ steps.schroot-cache.outputs.cache-hit != 'true' && env.HOST_DISTRO != 'focal' && env.HOST_DISTRO != 'jammy' && env.HOST_DISTRO != 'bookworm' && env.HOST_DISTRO != 'sid' }} + apt-get install -y cmake ninja-build + - name: Populate dependencie (cmake, overwrite) + if: ${{ steps.schroot-cache.outputs.cache-hit != 'true' }} run: | - # fallback cmake: https://cmake.org/files/v3.12/cmake-3.12.4-Linux-x86_64.tar.gz - curl -L -O https://github.com/Kitware/CMake/releases/download/v3.22.3/cmake-3.22.3-linux-x86_64.tar.gz + curl -L -O https://github.com/Kitware/CMake/releases/download/v3.28.5/cmake-3.28.5-linux-x86_64.tar.gz sudo schroot --chroot "source:${{ env.HOST_DISTRO }}-${{ env.BUILD_ARCH }}-${{ env.HOST_ARCH }}" --user root -- \ - tar -C /usr --strip-components=1 -xvf cmake-3.22.3-linux-x86_64.tar.gz + tar -C /usr --strip-components=1 -xf cmake-3.28.5-linux-x86_64.tar.gz + sudo schroot --chroot "source:${{ env.HOST_DISTRO }}-${{ env.BUILD_ARCH }}-${{ env.HOST_ARCH }}" --user root -- \ + cmake --version rm -f *.tar.gz - - name: Populate depedencie (base) + - name: Populate dependencie (base) if: ${{ steps.schroot-cache.outputs.cache-hit != 'true' }} run: | sudo schroot --chroot "source:${{ env.HOST_DISTRO }}-${{ env.BUILD_ARCH }}-${{ env.HOST_ARCH }}" --user root -- \ apt-get install -y perl gcc g++ ninja-build - - name: Populate depedencie (zlib) + - name: Populate dependencie (zlib) if: ${{ steps.schroot-cache.outputs.cache-hit != 'true' }} run: | sudo schroot --chroot "source:${{ env.HOST_DISTRO }}-${{ env.BUILD_ARCH }}-${{ env.HOST_ARCH }}" --user root -- \ apt-get install -y zlib1g-dev:${{ env.HOST_ARCH }} - - name: Populate depedencie (gui, exclude some arches) + - name: Populate dependencie (gui, exclude some arches) if: ${{ steps.schroot-cache.outputs.cache-hit != 'true' && env.HOST_ARCH != 'armel' && env.HOST_ARCH != 'mipsel' && env.HOST_ARCH != 'mips64el' && env.HOST_ARCH != 'riscv64' }} run: | sudo schroot --chroot "source:${{ env.HOST_DISTRO }}-${{ env.BUILD_ARCH }}-${{ env.HOST_ARCH }}" --user root -- \ - apt-get install -y libglib2.0-dev:${{ env.HOST_ARCH }} libgtk-3-dev:${{ env.HOST_ARCH }} - - name: Populate depedencie (curl, for test purpose, exclude some arches) + apt-get -o DPkg::Options::="--force-confnew" install -y libglib2.0-dev:${{ env.HOST_ARCH }} libgtk-3-dev:${{ env.HOST_ARCH }} + - name: Populate dependencie (curl, for test purpose, exclude some arches) if: ${{ steps.schroot-cache.outputs.cache-hit != 'true' && env.HOST_ARCH != 'armel' && env.HOST_ARCH != 'mipsel' && env.HOST_ARCH != 'mips64el' && env.HOST_ARCH != 'riscv64' }} run: | sudo schroot --chroot "source:${{ env.HOST_DISTRO }}-${{ env.BUILD_ARCH }}-${{ env.HOST_ARCH }}" --user root -- \ apt-get install -y libcurl4-openssl-dev:${{ env.HOST_ARCH }} - - name: Populate depedencie (list upgradable packages) + - name: Populate dependencie (list upgradable packages) run: | sudo schroot --chroot "source:${{ env.HOST_DISTRO }}-${{ env.BUILD_ARCH }}-${{ env.HOST_ARCH }}" --user root -- \ apt list --upgradeable || true diff --git a/yass/scripts/get-debian-name.py b/yass/scripts/get-debian-name.py index a6e0179b30..51d7c78137 100755 --- a/yass/scripts/get-debian-name.py +++ b/yass/scripts/get-debian-name.py @@ -16,6 +16,7 @@ codenames = { "jammy" : "ubuntu-22.04-jammy", "lunar" : "ubuntu-23.04-lunar", "mantic" : "ubuntu-23.10-mantic", + "noble" : "ubuntu-24.04-noble", "stretch" : "debian-9-stretch", "buster" : "debian-10-buster", "bullseye" : "debian-11-bullseye",