mirror of
https://github.com/bolucat/Archive.git
synced 2025-10-03 23:37:09 +08:00
Update On Sun May 26 20:29:40 CEST 2024
This commit is contained in:
1
.github/update.log
vendored
1
.github/update.log
vendored
@@ -658,3 +658,4 @@ Update On Wed May 22 20:31:05 CEST 2024
|
|||||||
Update On Thu May 23 20:29:12 CEST 2024
|
Update On Thu May 23 20:29:12 CEST 2024
|
||||||
Update On Fri May 24 20:29:24 CEST 2024
|
Update On Fri May 24 20:29:24 CEST 2024
|
||||||
Update On Sat May 25 20:28:13 CEST 2024
|
Update On Sat May 25 20:28:13 CEST 2024
|
||||||
|
Update On Sun May 26 20:29:29 CEST 2024
|
||||||
|
15
clash-nyanpasu/backend/Cargo.lock
generated
15
clash-nyanpasu/backend/Cargo.lock
generated
@@ -932,7 +932,7 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
"winreg 0.52.0",
|
"winreg 0.52.0",
|
||||||
"wry",
|
"wry",
|
||||||
"zip 2.0.0",
|
"zip 2.1.0",
|
||||||
"zip-extensions",
|
"zip-extensions",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -5109,18 +5109,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.202"
|
version = "1.0.203"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395"
|
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.202"
|
version = "1.0.203"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838"
|
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -7833,9 +7833,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zip"
|
name = "zip"
|
||||||
version = "2.0.0"
|
version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fccb210625924ecbbe92f9bb497d04b167b64fe5540cec75f10b16e0c51ee92b"
|
checksum = "e2568cd0f20e86cd9a7349fe05178f7bd22f22724678448ae5a9bac266df2689"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"arbitrary",
|
"arbitrary",
|
||||||
@@ -7849,6 +7849,7 @@ dependencies = [
|
|||||||
"hmac",
|
"hmac",
|
||||||
"indexmap 2.2.6",
|
"indexmap 2.2.6",
|
||||||
"lzma-rs",
|
"lzma-rs",
|
||||||
|
"memchr",
|
||||||
"pbkdf2 0.12.2",
|
"pbkdf2 0.12.2",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"sha1",
|
"sha1",
|
||||||
|
@@ -4,6 +4,7 @@ import {
|
|||||||
FilterDrama,
|
FilterDrama,
|
||||||
InsertDriveFile,
|
InsertDriveFile,
|
||||||
FiberManualRecord,
|
FiberManualRecord,
|
||||||
|
Terminal,
|
||||||
} from "@mui/icons-material";
|
} from "@mui/icons-material";
|
||||||
import LoadingButton from "@mui/lab/LoadingButton";
|
import LoadingButton from "@mui/lab/LoadingButton";
|
||||||
import {
|
import {
|
||||||
@@ -14,7 +15,8 @@ import {
|
|||||||
Menu,
|
Menu,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
useTheme,
|
useTheme,
|
||||||
lighten,
|
Button,
|
||||||
|
alpha,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { Profile, useClash } from "@nyanpasu/interface";
|
import { Profile, useClash } from "@nyanpasu/interface";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
@@ -27,11 +29,15 @@ import { useLockFn, useSetState } from "ahooks";
|
|||||||
export interface ProfileItemProps {
|
export interface ProfileItemProps {
|
||||||
item: Profile.Item;
|
item: Profile.Item;
|
||||||
selected?: boolean;
|
selected?: boolean;
|
||||||
|
onClickChains: (item: Profile.Item) => void;
|
||||||
|
chainsSelected?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ProfileItem = memo(function ProfileItem({
|
export const ProfileItem = memo(function ProfileItem({
|
||||||
item,
|
item,
|
||||||
selected,
|
selected,
|
||||||
|
onClickChains,
|
||||||
|
chainsSelected,
|
||||||
}: ProfileItemProps) {
|
}: ProfileItemProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -141,6 +147,7 @@ export const ProfileItem = memo(function ProfileItem({
|
|||||||
const menuMapping = {
|
const menuMapping = {
|
||||||
Select: () => handleSelect(),
|
Select: () => handleSelect(),
|
||||||
Edit: () => setOpen(true),
|
Edit: () => setOpen(true),
|
||||||
|
Chains: () => onClickChains(item),
|
||||||
"Open File": () => viewProfile(item.uid),
|
"Open File": () => viewProfile(item.uid),
|
||||||
Update: () => handleUpdate(),
|
Update: () => handleUpdate(),
|
||||||
"Update(Proxy)": () => handleUpdate(true),
|
"Update(Proxy)": () => handleUpdate(true),
|
||||||
@@ -156,7 +163,7 @@ export const ProfileItem = memo(function ProfileItem({
|
|||||||
sx={{
|
sx={{
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
backgroundColor: selected
|
backgroundColor: selected
|
||||||
? lighten(palette.primary.main, 0.9)
|
? alpha(palette.primary.main, 0.2)
|
||||||
: undefined,
|
: undefined,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -201,6 +208,16 @@ export const ProfileItem = memo(function ProfileItem({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="flex gap-2 justify-end">
|
<div className="flex gap-2 justify-end">
|
||||||
|
<Button
|
||||||
|
className="!mr-auto"
|
||||||
|
size="small"
|
||||||
|
variant={chainsSelected ? "contained" : "outlined"}
|
||||||
|
startIcon={<Terminal />}
|
||||||
|
onClick={() => onClickChains(item)}
|
||||||
|
>
|
||||||
|
Chains
|
||||||
|
</Button>
|
||||||
|
|
||||||
{isRemote && (
|
{isRemote && (
|
||||||
<LoadingButton
|
<LoadingButton
|
||||||
size="small"
|
size="small"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { forwardRef, useImperativeHandle, useRef } from "react";
|
import { forwardRef, useEffect, useImperativeHandle, useRef } from "react";
|
||||||
import { monaco } from "@/services/monaco";
|
import { monaco } from "@/services/monaco";
|
||||||
import { useDebounceEffect } from "ahooks";
|
import { useDebounceEffect, useUpdateEffect } from "ahooks";
|
||||||
import { themeMode } from "@/store";
|
import { themeMode } from "@/store";
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
|
|
||||||
@@ -53,5 +53,13 @@ export const ProfileMonacoView = forwardRef(function ProfileMonacoView(
|
|||||||
getValue: () => instanceRef.current?.getValue(),
|
getValue: () => instanceRef.current?.getValue(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
useUpdateEffect(() => {
|
||||||
|
if (!language) return;
|
||||||
|
|
||||||
|
monaco.editor.setModelLanguage(instanceRef.current!.getModel()!, language);
|
||||||
|
|
||||||
|
console.log(language, instanceRef.current?.getModel()?.getLanguageId());
|
||||||
|
}, [language]);
|
||||||
|
|
||||||
return open && <div ref={monacoRef} className={className} />;
|
return open && <div ref={monacoRef} className={className} />;
|
||||||
});
|
});
|
||||||
|
@@ -0,0 +1,200 @@
|
|||||||
|
import { Add, Close, Edit, RamenDining, Terminal } from "@mui/icons-material";
|
||||||
|
import {
|
||||||
|
Divider,
|
||||||
|
ListItemButton,
|
||||||
|
ListItemIcon,
|
||||||
|
ListItemText,
|
||||||
|
IconButton,
|
||||||
|
List,
|
||||||
|
useTheme,
|
||||||
|
alpha,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { Profile, useClash } from "@nyanpasu/interface";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { filterProfiles } from "./utils";
|
||||||
|
import { useLockFn } from "ahooks";
|
||||||
|
import { Expand, ExpandMore } from "@nyanpasu/ui";
|
||||||
|
import { isEmpty } from "lodash-es";
|
||||||
|
import { ScriptDialog } from "./script-dialog";
|
||||||
|
import { VList } from "virtua";
|
||||||
|
|
||||||
|
export interface ProfileSideProps {
|
||||||
|
profile?: Profile.Item;
|
||||||
|
global?: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ProfileSide = ({ profile, global, onClose }: ProfileSideProps) => {
|
||||||
|
const { palette } = useTheme();
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const { getProfiles, setProfilesConfig, getRuntimeLogs, setProfiles } =
|
||||||
|
useClash();
|
||||||
|
|
||||||
|
const { scripts } = filterProfiles(getProfiles.data?.items);
|
||||||
|
|
||||||
|
const handleChainClick = useLockFn(async (uid: string) => {
|
||||||
|
const chains = global
|
||||||
|
? getProfiles.data?.chain ?? []
|
||||||
|
: profile?.chains ?? [];
|
||||||
|
|
||||||
|
const updatedChains = chains.includes(uid)
|
||||||
|
? chains.filter((chain) => chain !== uid)
|
||||||
|
: [...chains, uid];
|
||||||
|
|
||||||
|
if (global) {
|
||||||
|
await setProfilesConfig({ chain: updatedChains });
|
||||||
|
} else {
|
||||||
|
await setProfiles(uid, { chains: updatedChains });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const [item, setItem] = useState<Profile.Item>();
|
||||||
|
|
||||||
|
const handleEditChain = async (item: Profile.Item) => {
|
||||||
|
setItem(item);
|
||||||
|
setOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const [expand, setExpand] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative h-full">
|
||||||
|
<div className="flex-col gap-2">
|
||||||
|
<div className="p-4 pr-2 flex justify-between items-start">
|
||||||
|
<div>
|
||||||
|
<div className="text-xl font-bold">Proxy Chains</div>
|
||||||
|
|
||||||
|
<div className="truncate">
|
||||||
|
{global ? "Global Chain" : profile?.name}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<IconButton onClick={onClose}>
|
||||||
|
<Close />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<List className="!pl-2 !pr-2 overflow-auto" disablePadding>
|
||||||
|
{scripts?.map((item, index) => {
|
||||||
|
const selected = global
|
||||||
|
? getProfiles.data?.chain?.includes(item.uid)
|
||||||
|
: profile?.chains?.includes(item.uid);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ListItemButton
|
||||||
|
key={index}
|
||||||
|
className="!mt-2 !mb-2"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: selected
|
||||||
|
? alpha(palette.primary.main, 0.3)
|
||||||
|
: alpha(palette.grey[100], 0.1),
|
||||||
|
borderRadius: 4,
|
||||||
|
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: selected
|
||||||
|
? alpha(palette.primary.main, 0.5)
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onClick={() => handleChainClick(item.uid)}
|
||||||
|
>
|
||||||
|
<ListItemText primary={item.name} secondary={item.desc} />
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
edge="end"
|
||||||
|
color="primary"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
handleEditChain(item);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Edit />
|
||||||
|
</IconButton>
|
||||||
|
</ListItemButton>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<ListItemButton
|
||||||
|
className="!mt-2!mb-2"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: alpha(palette.grey[100], 0.1),
|
||||||
|
borderRadius: 4,
|
||||||
|
}}
|
||||||
|
onClick={() => setOpen(true)}
|
||||||
|
>
|
||||||
|
<ListItemIcon>
|
||||||
|
<Add color="primary" />
|
||||||
|
</ListItemIcon>
|
||||||
|
|
||||||
|
<ListItemText primary="New Chian" />
|
||||||
|
</ListItemButton>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ScriptDialog
|
||||||
|
open={open}
|
||||||
|
item={item}
|
||||||
|
onClose={() => {
|
||||||
|
setOpen(false);
|
||||||
|
setItem(undefined);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="absolute bottom-0 z-10 w-full">
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<div className="p-1 pl-4 flex justify-between items-center">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Terminal />
|
||||||
|
|
||||||
|
<span>Console</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ExpandMore
|
||||||
|
size="small"
|
||||||
|
reverse
|
||||||
|
expand={expand}
|
||||||
|
onClick={() => setExpand(!expand)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Expand open={expand}>
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<VList className="flex flex-col gap-2 p-2 overflow-auto min-h-48 max-h-48">
|
||||||
|
{!isEmpty(getRuntimeLogs.data) ? (
|
||||||
|
Object.entries(getRuntimeLogs.data).map(([uid, content]) => {
|
||||||
|
return content.map((item, index) => {
|
||||||
|
const name = scripts?.find(
|
||||||
|
(script) => script.uid === uid,
|
||||||
|
)?.name;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{index !== 0 && <Divider />}
|
||||||
|
|
||||||
|
<div key={uid + index} className="w-full font-mono">
|
||||||
|
<span className="text-red-500">[{name}]: </span>
|
||||||
|
<span>{item}</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<div className="w-full h-full min-h-48 flex flex-col justify-center items-center">
|
||||||
|
<RamenDining className="!size-10" />
|
||||||
|
<p>No Log</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</VList>
|
||||||
|
</Expand>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProfileSide;
|
@@ -0,0 +1,199 @@
|
|||||||
|
import { Divider } from "@mui/material";
|
||||||
|
import { BaseDialog, BaseDialogProps } from "@nyanpasu/ui";
|
||||||
|
import { useRef } from "react";
|
||||||
|
import { useAsyncEffect, useReactive } from "ahooks";
|
||||||
|
import { Profile, useClash } from "@nyanpasu/interface";
|
||||||
|
import { ProfileMonacoView, ProfileMonacoViewRef } from "./profile-monaco-view";
|
||||||
|
import { SelectElement, TextFieldElement, useForm } from "react-hook-form-mui";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { isEqual } from "lodash-es";
|
||||||
|
|
||||||
|
export interface ScriptDialogProps extends Omit<BaseDialogProps, "title"> {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
item?: Profile.Item;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ScriptDialog = ({
|
||||||
|
open,
|
||||||
|
item,
|
||||||
|
onClose,
|
||||||
|
...props
|
||||||
|
}: ScriptDialogProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const { getProfileFile, setProfileFile, createProfile, setProfiles } =
|
||||||
|
useClash();
|
||||||
|
|
||||||
|
const optionTypeMapping = [
|
||||||
|
{
|
||||||
|
id: "js",
|
||||||
|
value: { script: "javascript" },
|
||||||
|
language: "javascript",
|
||||||
|
label: t("JavaScript"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "lua",
|
||||||
|
value: { script: "lua" },
|
||||||
|
language: "lua",
|
||||||
|
label: t("LuaScript"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "merge",
|
||||||
|
value: "merge",
|
||||||
|
language: "yaml",
|
||||||
|
label: t("Merge"),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const preprocessing = () => {
|
||||||
|
const result = optionTypeMapping.find((option) =>
|
||||||
|
isEqual(option.value, item?.type),
|
||||||
|
);
|
||||||
|
|
||||||
|
return { ...item, type: result?.id } as Profile.Item;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { control, watch, handleSubmit, reset } = useForm<Profile.Item>({
|
||||||
|
defaultValues: item
|
||||||
|
? preprocessing()
|
||||||
|
: {
|
||||||
|
type: "merge",
|
||||||
|
chains: [],
|
||||||
|
name: "New Script",
|
||||||
|
desc: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const profileMonacoViewRef = useRef<ProfileMonacoViewRef>(null);
|
||||||
|
|
||||||
|
const editor = useReactive({
|
||||||
|
value: "",
|
||||||
|
language: "javascript",
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleTypeChange = () => {
|
||||||
|
const language = optionTypeMapping.find((option) =>
|
||||||
|
isEqual(option.id, watch("type")),
|
||||||
|
)?.language;
|
||||||
|
|
||||||
|
if (language) {
|
||||||
|
editor.language = language;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const isEdit = Boolean(item);
|
||||||
|
|
||||||
|
const commonProps = {
|
||||||
|
autoComplete: "off",
|
||||||
|
autoCorrect: "off",
|
||||||
|
fullWidth: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = handleSubmit(async (form) => {
|
||||||
|
const value = profileMonacoViewRef.current?.getValue() || "";
|
||||||
|
|
||||||
|
const type = optionTypeMapping.find((option) =>
|
||||||
|
isEqual(option.id, form.type),
|
||||||
|
)?.value;
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
...form,
|
||||||
|
type,
|
||||||
|
} as Profile.Item;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (isEdit) {
|
||||||
|
await setProfiles(data.uid, data);
|
||||||
|
|
||||||
|
await setProfileFile(data.uid, value);
|
||||||
|
} else {
|
||||||
|
await createProfile(data, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => reset(), 300);
|
||||||
|
|
||||||
|
onClose();
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useAsyncEffect(async () => {
|
||||||
|
editor.value = await getProfileFile(item?.uid);
|
||||||
|
|
||||||
|
if (item) {
|
||||||
|
reset(item);
|
||||||
|
} else {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BaseDialog
|
||||||
|
title={isEdit ? "Edit Script" : "New Script"}
|
||||||
|
open={open}
|
||||||
|
onClose={() => onClose()}
|
||||||
|
onOk={onSubmit}
|
||||||
|
divider
|
||||||
|
sx={{
|
||||||
|
" .MuiDialog-paper": {
|
||||||
|
maxWidth: "90vw",
|
||||||
|
maxHeight: "90vh",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
contentSx={{
|
||||||
|
overflow: "auto",
|
||||||
|
width: "90vw",
|
||||||
|
height: "90vh",
|
||||||
|
padding: 0,
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<div className="flex h-full">
|
||||||
|
<div className="pt-4 pb-4 overflow-auto">
|
||||||
|
<div className="flex flex-col gap-4 pl-4 pr-4 pb-4">
|
||||||
|
{!isEdit && (
|
||||||
|
<SelectElement
|
||||||
|
label={t("Type")}
|
||||||
|
name="type"
|
||||||
|
control={control}
|
||||||
|
{...commonProps}
|
||||||
|
size="small"
|
||||||
|
required
|
||||||
|
options={optionTypeMapping}
|
||||||
|
onChange={() => handleTypeChange()}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<TextFieldElement
|
||||||
|
label={t("Name")}
|
||||||
|
name="name"
|
||||||
|
control={control}
|
||||||
|
{...commonProps}
|
||||||
|
size="small"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextFieldElement
|
||||||
|
label={t("Descriptions")}
|
||||||
|
name="desc"
|
||||||
|
control={control}
|
||||||
|
{...commonProps}
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Divider orientation="vertical" />
|
||||||
|
|
||||||
|
<ProfileMonacoView
|
||||||
|
className="w-full"
|
||||||
|
ref={profileMonacoViewRef}
|
||||||
|
open={open}
|
||||||
|
value={editor.value}
|
||||||
|
language={editor.language}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</BaseDialog>
|
||||||
|
);
|
||||||
|
};
|
@@ -13,9 +13,12 @@ import { proxyGroupAtom, proxyGroupSortAtom } from "@/store";
|
|||||||
import { CSSProperties, memo, useEffect, useMemo, useState } from "react";
|
import { CSSProperties, memo, useEffect, useMemo, useState } from "react";
|
||||||
import { classNames } from "@/utils";
|
import { classNames } from "@/utils";
|
||||||
import { VList } from "virtua";
|
import { VList } from "virtua";
|
||||||
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
|
|
||||||
type History = Clash.Proxy["history"];
|
type History = Clash.Proxy["history"];
|
||||||
|
|
||||||
|
type RenderClashProxy = Clash.Proxy<string> & { renderLayoutKey: string };
|
||||||
|
|
||||||
const filterDelay = (history?: History): number => {
|
const filterDelay = (history?: History): number => {
|
||||||
if (!history || history.length == 0) {
|
if (!history || history.length == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -218,15 +221,36 @@ export const NodeList = () => {
|
|||||||
default: 4,
|
default: 4,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [renderList, setRenderList] = useState<Clash.Proxy<string>[][]>([]);
|
const [renderList, setRenderList] = useState<RenderClashProxy[][]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!group?.all) return;
|
if (!group?.all) return;
|
||||||
|
|
||||||
const list = group?.all?.reduce<Clash.Proxy<string>[][]>(
|
const nodeNames: string[] = [];
|
||||||
|
|
||||||
|
const list = group?.all?.reduce<RenderClashProxy[][]>(
|
||||||
(result, value, index) => {
|
(result, value, index) => {
|
||||||
if (index % column === 0) result.push([]);
|
const getKey = () => {
|
||||||
result[Math.floor(index / column)].push(value);
|
const filter = nodeNames.filter((i) => i === value.name);
|
||||||
|
|
||||||
|
if (filter.length === 0) {
|
||||||
|
return value.name;
|
||||||
|
} else {
|
||||||
|
return `${value.name}-${filter.length}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (index % column === 0) {
|
||||||
|
result.push([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
result[Math.floor(index / column)].push({
|
||||||
|
...value,
|
||||||
|
renderLayoutKey: getKey(),
|
||||||
|
});
|
||||||
|
|
||||||
|
nodeNames.push(value.name);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
@@ -240,35 +264,42 @@ export const NodeList = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VList style={{ flex: 1 }} className="p-2">
|
<AnimatePresence initial={false}>
|
||||||
{renderList?.map((node, index) => {
|
<VList style={{ flex: 1 }} className="p-2">
|
||||||
return (
|
{renderList?.map((node, index) => {
|
||||||
<div key={index} className="flex">
|
return (
|
||||||
{node.map((render, index) => {
|
<div
|
||||||
return (
|
key={index}
|
||||||
<div
|
className="grid gap-2 pb-2"
|
||||||
key={index}
|
style={{ gridTemplateColumns: `repeat(${column} , 1fr)` }}
|
||||||
className="relative p-2"
|
>
|
||||||
style={{
|
{node.map((render) => {
|
||||||
flex: 1 / column,
|
return (
|
||||||
width: `calc(100% / ${column})`,
|
<motion.div
|
||||||
}}
|
key={render.name}
|
||||||
>
|
layoutId={`node-${render.renderLayoutKey}`}
|
||||||
<NodeCard
|
className="relative overflow-hidden"
|
||||||
node={render}
|
layout="position"
|
||||||
now={group?.now}
|
initial={false}
|
||||||
disabled={group?.type !== "Selector"}
|
animate="center"
|
||||||
onClick={() => hendleClick(render.name)}
|
exit="exit"
|
||||||
onClickDelay={async () => {
|
>
|
||||||
await updateProxiesDelay(render.name);
|
<NodeCard
|
||||||
}}
|
node={render}
|
||||||
/>
|
now={group?.now}
|
||||||
</div>
|
disabled={group?.type !== "Selector"}
|
||||||
);
|
onClick={() => hendleClick(render.name)}
|
||||||
})}
|
onClickDelay={async () => {
|
||||||
</div>
|
await updateProxiesDelay(render.name);
|
||||||
);
|
}}
|
||||||
})}
|
/>
|
||||||
</VList>
|
</motion.div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</VList>
|
||||||
|
</AnimatePresence>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@@ -1,48 +1,102 @@
|
|||||||
import { Button, alpha, useTheme } from "@mui/material";
|
import { Button } from "@mui/material";
|
||||||
import { useNyanpasu } from "@nyanpasu/interface";
|
import { Profile, useClash } from "@nyanpasu/interface";
|
||||||
import { SidePage } from "@nyanpasu/ui";
|
import { SidePage } from "@nyanpasu/ui";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import Grid from "@mui/material/Unstable_Grid2";
|
|
||||||
import { Add } from "@mui/icons-material";
|
|
||||||
import ProfileItem from "@/components/profiles/profile-item";
|
import ProfileItem from "@/components/profiles/profile-item";
|
||||||
|
import ProfileSide from "@/components/profiles/profile-side";
|
||||||
import { filterProfiles } from "@/components/profiles/utils";
|
import { filterProfiles } from "@/components/profiles/utils";
|
||||||
|
import NewProfileButton from "@/components/profiles/new-profile-button";
|
||||||
|
import { QuickImport } from "@/components/profiles/quick-import";
|
||||||
|
import Masonry from "@mui/lab/Masonry";
|
||||||
|
|
||||||
export const ProfilePage = () => {
|
export const ProfilePage = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { getProfiles } = useNyanpasu();
|
const { getProfiles } = useClash();
|
||||||
|
|
||||||
const { profiles } = filterProfiles(getProfiles.data?.items);
|
const { profiles, scripts } = filterProfiles(getProfiles.data?.items);
|
||||||
|
|
||||||
const { palette } = useTheme();
|
useEffect(() => {
|
||||||
|
console.log("getProfiles.data:", getProfiles.data);
|
||||||
|
console.log("profiles:", profiles);
|
||||||
|
console.log("scripts:", scripts);
|
||||||
|
}, [getProfiles.data?.items]);
|
||||||
|
|
||||||
|
const [globalChain, setGlobalChain] = useState(false);
|
||||||
|
|
||||||
|
const handleGlobalChainClick = () => {
|
||||||
|
setChainsSelected(undefined);
|
||||||
|
setGlobalChain(!globalChain);
|
||||||
|
};
|
||||||
|
|
||||||
|
const [chainsSelected, setChainsSelected] = useState<Profile.Item>();
|
||||||
|
|
||||||
|
const onClickChains = (profile: Profile.Item) => {
|
||||||
|
setGlobalChain(false);
|
||||||
|
|
||||||
|
if (chainsSelected?.uid == profile.uid) {
|
||||||
|
setChainsSelected(undefined);
|
||||||
|
} else {
|
||||||
|
setChainsSelected(profile);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSideClose = () => {
|
||||||
|
setChainsSelected(undefined);
|
||||||
|
setGlobalChain(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidePage title={t("Profiles")} flexReverse>
|
<SidePage
|
||||||
<div className="p-6">
|
title={t("Profiles")}
|
||||||
<Grid container spacing={2}>
|
flexReverse
|
||||||
{profiles?.map((item, index) => {
|
header={
|
||||||
return (
|
<div>
|
||||||
<Grid key={index} xs={12} sm={6} md={6} xl={4}>
|
<Button
|
||||||
<ProfileItem item={item} />
|
variant={globalChain ? "contained" : "outlined"}
|
||||||
</Grid>
|
onClick={handleGlobalChainClick}
|
||||||
);
|
>
|
||||||
})}
|
Global Chain
|
||||||
</Grid>
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
sideClassName="!overflow-visible"
|
||||||
|
side={
|
||||||
|
(globalChain || chainsSelected) && (
|
||||||
|
<ProfileSide
|
||||||
|
profile={chainsSelected}
|
||||||
|
global={globalChain}
|
||||||
|
onClose={handleSideClose}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="flex flex-col gap-4 p-6">
|
||||||
|
<QuickImport />
|
||||||
|
|
||||||
|
{profiles && (
|
||||||
|
<Masonry
|
||||||
|
columns={{ xs: 1, sm: 1, md: 2, xl: 3 }}
|
||||||
|
spacing={2}
|
||||||
|
sx={{ width: "calc(100% + 24px)" }}
|
||||||
|
>
|
||||||
|
{profiles.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<ProfileItem
|
||||||
|
key={index}
|
||||||
|
item={item}
|
||||||
|
onClickChains={onClickChains}
|
||||||
|
selected={getProfiles.data?.current == item.uid}
|
||||||
|
chainsSelected={chainsSelected?.uid == item.uid}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Masonry>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button
|
<NewProfileButton />
|
||||||
className="size-16 backdrop-blur !rounded-2xl !absolute z-10 bottom-8 right-8"
|
|
||||||
sx={{
|
|
||||||
boxShadow: 8,
|
|
||||||
backgroundColor: alpha(palette.primary.main, 0.3),
|
|
||||||
|
|
||||||
"&:hover": {
|
|
||||||
backgroundColor: alpha(palette.primary.main, 0.45),
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Add className="!size-8 absolute" />
|
|
||||||
</Button>
|
|
||||||
</SidePage>
|
</SidePage>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@@ -4,6 +4,7 @@ import useTheme from "@mui/material/styles/useTheme";
|
|||||||
|
|
||||||
interface ExpandMoreProps extends IconButtonProps {
|
interface ExpandMoreProps extends IconButtonProps {
|
||||||
expand: boolean;
|
expand: boolean;
|
||||||
|
reverse?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,14 +16,20 @@ interface ExpandMoreProps extends IconButtonProps {
|
|||||||
* @author keiko233 <i@elaina.moe>
|
* @author keiko233 <i@elaina.moe>
|
||||||
* @copyright LibNyanpasu org. 2024
|
* @copyright LibNyanpasu org. 2024
|
||||||
*/
|
*/
|
||||||
export const ExpandMore = ({ expand, ...props }: ExpandMoreProps) => {
|
export const ExpandMore = ({ expand, reverse, ...props }: ExpandMoreProps) => {
|
||||||
const { transitions } = useTheme();
|
const { transitions } = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IconButton {...props}>
|
<IconButton {...props}>
|
||||||
<ExpandMoreIcon
|
<ExpandMoreIcon
|
||||||
sx={{
|
sx={{
|
||||||
transform: !expand ? "rotate(0deg)" : "rotate(180deg)",
|
transform: !expand
|
||||||
|
? reverse
|
||||||
|
? "rotate(180deg)"
|
||||||
|
: "rotate(0deg)"
|
||||||
|
: reverse
|
||||||
|
? "rotate(0deg)"
|
||||||
|
: "rotate(180deg)",
|
||||||
marginLeft: "auto",
|
marginLeft: "auto",
|
||||||
transition: transitions.create("transform", {
|
transition: transitions.create("transform", {
|
||||||
duration: transitions.duration.shortest,
|
duration: transitions.duration.shortest,
|
||||||
|
@@ -12,6 +12,7 @@ interface Props {
|
|||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
sideBar?: ReactNode;
|
sideBar?: ReactNode;
|
||||||
side?: ReactNode;
|
side?: ReactNode;
|
||||||
|
sideClassName?: string;
|
||||||
toolBar?: ReactNode;
|
toolBar?: ReactNode;
|
||||||
noChildrenScroll?: boolean;
|
noChildrenScroll?: boolean;
|
||||||
flexReverse?: boolean;
|
flexReverse?: boolean;
|
||||||
@@ -43,6 +44,7 @@ export const SidePage: FC<Props> = ({
|
|||||||
children,
|
children,
|
||||||
sideBar,
|
sideBar,
|
||||||
side,
|
side,
|
||||||
|
sideClassName,
|
||||||
toolBar,
|
toolBar,
|
||||||
noChildrenScroll,
|
noChildrenScroll,
|
||||||
flexReverse,
|
flexReverse,
|
||||||
@@ -82,7 +84,7 @@ export const SidePage: FC<Props> = ({
|
|||||||
{sideBar && <div>{sideBar}</div>}
|
{sideBar && <div>{sideBar}</div>}
|
||||||
|
|
||||||
<div className={style["LeftContainer-Content"]}>
|
<div className={style["LeftContainer-Content"]}>
|
||||||
<section>{side}</section>
|
<section className={sideClassName}>{side}</section>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
|
@@ -1,3 +1,25 @@
|
|||||||
|
## v1.6.4
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- 系统代理支持 PAC 模式
|
||||||
|
- 允许关闭不使用的端口
|
||||||
|
- 使用新的应用图标
|
||||||
|
- MacOS 支持切换托盘图标单色/彩色模式
|
||||||
|
- CSS 注入支持通过编辑器编辑
|
||||||
|
- 优化代理组列表性能
|
||||||
|
- 优化流量图显性能
|
||||||
|
- 支持波斯语
|
||||||
|
|
||||||
|
### Bugs Fixes
|
||||||
|
|
||||||
|
- Kill 内核后 Tun 开启缓慢的问题
|
||||||
|
- 代理绕过为空时使用默认值
|
||||||
|
- 无法读取剪切板内容
|
||||||
|
- Windows 下覆盖安装无法内核占用问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## v1.6.2
|
## v1.6.2
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
@@ -16,6 +38,8 @@
|
|||||||
- Linux 下与 N 卡的兼容性问题
|
- Linux 下与 N 卡的兼容性问题
|
||||||
- 修改 Tun 设置不立即生效
|
- 修改 Tun 设置不立即生效
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## v1.6.1
|
## v1.6.1
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "clash-verge",
|
"name": "clash-verge",
|
||||||
"version": "1.6.2",
|
"version": "1.6.4",
|
||||||
"license": "GPL-3.0-only",
|
"license": "GPL-3.0-only",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "tauri dev",
|
"dev": "tauri dev",
|
||||||
@@ -32,7 +32,6 @@
|
|||||||
"@types/json-schema": "^7.0.15",
|
"@types/json-schema": "^7.0.15",
|
||||||
"ahooks": "^3.7.11",
|
"ahooks": "^3.7.11",
|
||||||
"axios": "^1.6.8",
|
"axios": "^1.6.8",
|
||||||
"axios-tauri-api-adapter": "^0.2.1",
|
|
||||||
"dayjs": "1.11.5",
|
"dayjs": "1.11.5",
|
||||||
"i18next": "^23.11.3",
|
"i18next": "^23.11.3",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
|
63
clash-verge-rev/pnpm-lock.yaml
generated
63
clash-verge-rev/pnpm-lock.yaml
generated
@@ -49,9 +49,6 @@ importers:
|
|||||||
axios:
|
axios:
|
||||||
specifier: ^1.6.8
|
specifier: ^1.6.8
|
||||||
version: 1.6.8
|
version: 1.6.8
|
||||||
axios-tauri-api-adapter:
|
|
||||||
specifier: ^0.2.1
|
|
||||||
version: 0.2.1
|
|
||||||
dayjs:
|
dayjs:
|
||||||
specifier: 1.11.5
|
specifier: 1.11.5
|
||||||
version: 1.11.5
|
version: 1.11.5
|
||||||
@@ -1605,13 +1602,6 @@ packages:
|
|||||||
integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==,
|
integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==,
|
||||||
}
|
}
|
||||||
|
|
||||||
axios-tauri-api-adapter@0.2.1:
|
|
||||||
resolution:
|
|
||||||
{
|
|
||||||
integrity: sha512-XuC6rDl8yOUrctN1nUe5fngPhmq+zhkUvKZVRCUOrlSn5UdLYH0OjrLJl7h8DQdxcAzZw0Oiw+PQFNOBuL42hg==,
|
|
||||||
}
|
|
||||||
engines: { node: ">=16", pnpm: ">=7" }
|
|
||||||
|
|
||||||
axios@1.6.8:
|
axios@1.6.8:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -1659,12 +1649,6 @@ packages:
|
|||||||
engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 }
|
engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 }
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
build-url-ts@6.1.7:
|
|
||||||
resolution:
|
|
||||||
{
|
|
||||||
integrity: sha512-KU8hfHxEpBTvoJA4XLiL88JiJN6U0SIVtnXKMSKgxf2T+bP3tDlzd/WIl/dthi+01YXeS49yUxkL3JXyqPdIAw==,
|
|
||||||
}
|
|
||||||
|
|
||||||
callsites@3.1.0:
|
callsites@3.1.0:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -2133,12 +2117,6 @@ packages:
|
|||||||
integrity: sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==,
|
integrity: sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==,
|
||||||
}
|
}
|
||||||
|
|
||||||
http-status-codes@2.3.0:
|
|
||||||
resolution:
|
|
||||||
{
|
|
||||||
integrity: sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==,
|
|
||||||
}
|
|
||||||
|
|
||||||
https-proxy-agent@5.0.1:
|
https-proxy-agent@5.0.1:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -2913,12 +2891,6 @@ packages:
|
|||||||
integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==,
|
integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==,
|
||||||
}
|
}
|
||||||
|
|
||||||
querystringify@2.2.0:
|
|
||||||
resolution:
|
|
||||||
{
|
|
||||||
integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==,
|
|
||||||
}
|
|
||||||
|
|
||||||
react-dom@18.3.1:
|
react-dom@18.3.1:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -3080,12 +3052,6 @@ packages:
|
|||||||
integrity: sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==,
|
integrity: sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==,
|
||||||
}
|
}
|
||||||
|
|
||||||
requires-port@1.0.0:
|
|
||||||
resolution:
|
|
||||||
{
|
|
||||||
integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==,
|
|
||||||
}
|
|
||||||
|
|
||||||
reselect@4.1.8:
|
reselect@4.1.8:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -3390,12 +3356,6 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
browserslist: ">= 4.21.0"
|
browserslist: ">= 4.21.0"
|
||||||
|
|
||||||
url-parse@1.5.10:
|
|
||||||
resolution:
|
|
||||||
{
|
|
||||||
integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==,
|
|
||||||
}
|
|
||||||
|
|
||||||
vfile-message@4.0.2:
|
vfile-message@4.0.2:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@@ -4455,16 +4415,6 @@ snapshots:
|
|||||||
|
|
||||||
asynckit@0.4.0: {}
|
asynckit@0.4.0: {}
|
||||||
|
|
||||||
axios-tauri-api-adapter@0.2.1:
|
|
||||||
dependencies:
|
|
||||||
"@tauri-apps/api": 1.5.4
|
|
||||||
axios: 1.6.8
|
|
||||||
build-url-ts: 6.1.7
|
|
||||||
http-status-codes: 2.3.0
|
|
||||||
url-parse: 1.5.10
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- debug
|
|
||||||
|
|
||||||
axios@1.6.8:
|
axios@1.6.8:
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects: 1.15.6
|
follow-redirects: 1.15.6
|
||||||
@@ -4496,8 +4446,6 @@ snapshots:
|
|||||||
node-releases: 2.0.14
|
node-releases: 2.0.14
|
||||||
update-browserslist-db: 1.0.15(browserslist@4.23.0)
|
update-browserslist-db: 1.0.15(browserslist@4.23.0)
|
||||||
|
|
||||||
build-url-ts@6.1.7: {}
|
|
||||||
|
|
||||||
callsites@3.1.0: {}
|
callsites@3.1.0: {}
|
||||||
|
|
||||||
camelcase@6.3.0: {}
|
camelcase@6.3.0: {}
|
||||||
@@ -4774,8 +4722,6 @@ snapshots:
|
|||||||
|
|
||||||
html-url-attributes@3.0.0: {}
|
html-url-attributes@3.0.0: {}
|
||||||
|
|
||||||
http-status-codes@2.3.0: {}
|
|
||||||
|
|
||||||
https-proxy-agent@5.0.1:
|
https-proxy-agent@5.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 6.0.2
|
agent-base: 6.0.2
|
||||||
@@ -5293,8 +5239,6 @@ snapshots:
|
|||||||
end-of-stream: 1.4.4
|
end-of-stream: 1.4.4
|
||||||
once: 1.4.0
|
once: 1.4.0
|
||||||
|
|
||||||
querystringify@2.2.0: {}
|
|
||||||
|
|
||||||
react-dom@18.3.1(react@18.3.1):
|
react-dom@18.3.1(react@18.3.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
loose-envify: 1.4.0
|
loose-envify: 1.4.0
|
||||||
@@ -5404,8 +5348,6 @@ snapshots:
|
|||||||
unified: 11.0.4
|
unified: 11.0.4
|
||||||
vfile: 6.0.1
|
vfile: 6.0.1
|
||||||
|
|
||||||
requires-port@1.0.0: {}
|
|
||||||
|
|
||||||
reselect@4.1.8: {}
|
reselect@4.1.8: {}
|
||||||
|
|
||||||
resize-observer-polyfill@1.5.1: {}
|
resize-observer-polyfill@1.5.1: {}
|
||||||
@@ -5581,11 +5523,6 @@ snapshots:
|
|||||||
escalade: 3.1.2
|
escalade: 3.1.2
|
||||||
picocolors: 1.0.0
|
picocolors: 1.0.0
|
||||||
|
|
||||||
url-parse@1.5.10:
|
|
||||||
dependencies:
|
|
||||||
querystringify: 2.2.0
|
|
||||||
requires-port: 1.0.0
|
|
||||||
|
|
||||||
vfile-message@4.0.2:
|
vfile-message@4.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/unist": 3.0.2
|
"@types/unist": 3.0.2
|
||||||
|
4
clash-verge-rev/src-tauri/Cargo.lock
generated
4
clash-verge-rev/src-tauri/Cargo.lock
generated
@@ -788,7 +788,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clash-verge"
|
name = "clash-verge"
|
||||||
version = "1.6.2"
|
version = "1.6.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"auto-launch",
|
"auto-launch",
|
||||||
@@ -5169,7 +5169,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "sysproxy"
|
name = "sysproxy"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/zzzgydi/sysproxy-rs?branch=main#1402eba27022a2da7b91b3090d2f4936b6260f10"
|
source = "git+https://github.com/zzzgydi/sysproxy-rs?branch=main#24e8d46cb338a6a8e28742dea6ed993cd6450780"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"interfaces",
|
"interfaces",
|
||||||
"iptools",
|
"iptools",
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "clash-verge"
|
name = "clash-verge"
|
||||||
version = "1.6.2"
|
version = "1.6.4"
|
||||||
description = "clash verge"
|
description = "clash verge"
|
||||||
authors = ["zzzgydi", "wonfen", "MystiPanda"]
|
authors = ["zzzgydi", "wonfen", "MystiPanda"]
|
||||||
license = "GPL-3.0-only"
|
license = "GPL-3.0-only"
|
||||||
@@ -37,7 +37,7 @@ serde = { version = "1.0", features = ["derive"] }
|
|||||||
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
|
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
|
||||||
sysproxy = { git="https://github.com/zzzgydi/sysproxy-rs", branch = "main" }
|
sysproxy = { git="https://github.com/zzzgydi/sysproxy-rs", branch = "main" }
|
||||||
auto-launch = { git="https://github.com/zzzgydi/auto-launch", branch = "main" }
|
auto-launch = { git="https://github.com/zzzgydi/auto-launch", branch = "main" }
|
||||||
tauri = { version = "1.6", features = [ "http-all", "fs-read-file", "fs-exists", "path-all", "protocol-asset", "dialog-open", "notification-all", "icon-png", "icon-ico", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "devtools"] }
|
tauri = { version = "1.6", features = [ "fs-read-file", "fs-exists", "path-all", "protocol-asset", "dialog-open", "notification-all", "icon-png", "icon-ico", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all", "devtools"] }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
runas = "=1.2.0"
|
runas = "=1.2.0"
|
||||||
|
@@ -8,7 +8,7 @@ use crate::{ret_err, wrap_err};
|
|||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use serde_yaml::Mapping;
|
use serde_yaml::Mapping;
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
use sysproxy::Sysproxy;
|
use sysproxy::{Autoproxy, Sysproxy};
|
||||||
use tauri::{api, Manager};
|
use tauri::{api, Manager};
|
||||||
type CmdResult<T = ()> = Result<T, String>;
|
type CmdResult<T = ()> = Result<T, String>;
|
||||||
|
|
||||||
@@ -194,7 +194,6 @@ pub fn grant_permission(_core: String) -> CmdResult {
|
|||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn get_sys_proxy() -> CmdResult<Mapping> {
|
pub fn get_sys_proxy() -> CmdResult<Mapping> {
|
||||||
let current = wrap_err!(Sysproxy::get_system_proxy())?;
|
let current = wrap_err!(Sysproxy::get_system_proxy())?;
|
||||||
|
|
||||||
let mut map = Mapping::new();
|
let mut map = Mapping::new();
|
||||||
map.insert("enable".into(), current.enable.into());
|
map.insert("enable".into(), current.enable.into());
|
||||||
map.insert(
|
map.insert(
|
||||||
@@ -206,6 +205,18 @@ pub fn get_sys_proxy() -> CmdResult<Mapping> {
|
|||||||
Ok(map)
|
Ok(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// get the system proxy
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn get_auto_proxy() -> CmdResult<Mapping> {
|
||||||
|
let current = wrap_err!(Autoproxy::get_auto_proxy())?;
|
||||||
|
|
||||||
|
let mut map = Mapping::new();
|
||||||
|
map.insert("enable".into(), current.enable.into());
|
||||||
|
map.insert("url".into(), current.url.into());
|
||||||
|
|
||||||
|
Ok(map)
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn get_clash_logs() -> CmdResult<VecDeque<String>> {
|
pub fn get_clash_logs() -> CmdResult<VecDeque<String>> {
|
||||||
Ok(logger::Logger::global().get_log())
|
Ok(logger::Logger::global().get_log())
|
||||||
|
@@ -13,3 +13,8 @@ pub use self::prfitem::*;
|
|||||||
pub use self::profiles::*;
|
pub use self::profiles::*;
|
||||||
pub use self::runtime::*;
|
pub use self::runtime::*;
|
||||||
pub use self::verge::*;
|
pub use self::verge::*;
|
||||||
|
|
||||||
|
pub const DEFAULT_PAC: &str = r#"function FindProxyForURL(url, host) {
|
||||||
|
return "PROXY 127.0.0.1:%mixed-port%; SOCKS5 127.0.0.1:%mixed-port%; DIRECT;";
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::config::DEFAULT_PAC;
|
||||||
use crate::utils::{dirs, help};
|
use crate::utils::{dirs, help};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
@@ -80,6 +81,12 @@ pub struct IVerge {
|
|||||||
/// proxy guard duration
|
/// proxy guard duration
|
||||||
pub proxy_guard_duration: Option<u64>,
|
pub proxy_guard_duration: Option<u64>,
|
||||||
|
|
||||||
|
/// use pac mode
|
||||||
|
pub proxy_auto_config: Option<bool>,
|
||||||
|
|
||||||
|
/// pac script content
|
||||||
|
pub pac_file_content: Option<String>,
|
||||||
|
|
||||||
/// theme setting
|
/// theme setting
|
||||||
pub theme_setting: Option<IVergeTheme>,
|
pub theme_setting: Option<IVergeTheme>,
|
||||||
|
|
||||||
@@ -211,6 +218,8 @@ impl IVerge {
|
|||||||
enable_auto_launch: Some(false),
|
enable_auto_launch: Some(false),
|
||||||
enable_silent_start: Some(false),
|
enable_silent_start: Some(false),
|
||||||
enable_system_proxy: Some(false),
|
enable_system_proxy: Some(false),
|
||||||
|
proxy_auto_config: Some(false),
|
||||||
|
pac_file_content: Some(DEFAULT_PAC.into()),
|
||||||
enable_random_port: Some(false),
|
enable_random_port: Some(false),
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
verge_redir_port: Some(7895),
|
verge_redir_port: Some(7895),
|
||||||
@@ -290,6 +299,8 @@ impl IVerge {
|
|||||||
patch!(enable_proxy_guard);
|
patch!(enable_proxy_guard);
|
||||||
patch!(system_proxy_bypass);
|
patch!(system_proxy_bypass);
|
||||||
patch!(proxy_guard_duration);
|
patch!(proxy_guard_duration);
|
||||||
|
patch!(proxy_auto_config);
|
||||||
|
patch!(pac_file_content);
|
||||||
|
|
||||||
patch!(theme_setting);
|
patch!(theme_setting);
|
||||||
patch!(web_ui_list);
|
patch!(web_ui_list);
|
||||||
|
@@ -1,11 +1,14 @@
|
|||||||
use crate::{config::Config, log_err};
|
use crate::{
|
||||||
|
config::{Config, IVerge},
|
||||||
|
log_err,
|
||||||
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use auto_launch::{AutoLaunch, AutoLaunchBuilder};
|
use auto_launch::{AutoLaunch, AutoLaunchBuilder};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::env::current_exe;
|
use std::env::current_exe;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use sysproxy::Sysproxy;
|
use sysproxy::{Autoproxy, Sysproxy};
|
||||||
use tauri::async_runtime::Mutex as TokioMutex;
|
use tauri::async_runtime::Mutex as TokioMutex;
|
||||||
|
|
||||||
pub struct Sysopt {
|
pub struct Sysopt {
|
||||||
@@ -16,6 +19,13 @@ pub struct Sysopt {
|
|||||||
/// recover it when exit
|
/// recover it when exit
|
||||||
old_sysproxy: Arc<Mutex<Option<Sysproxy>>>,
|
old_sysproxy: Arc<Mutex<Option<Sysproxy>>>,
|
||||||
|
|
||||||
|
/// current auto proxy setting
|
||||||
|
cur_autoproxy: Arc<Mutex<Option<Autoproxy>>>,
|
||||||
|
|
||||||
|
/// record the original auto proxy
|
||||||
|
/// recover it when exit
|
||||||
|
old_autoproxy: Arc<Mutex<Option<Autoproxy>>>,
|
||||||
|
|
||||||
/// helps to auto launch the app
|
/// helps to auto launch the app
|
||||||
auto_launch: Arc<Mutex<Option<AutoLaunch>>>,
|
auto_launch: Arc<Mutex<Option<AutoLaunch>>>,
|
||||||
|
|
||||||
@@ -38,6 +48,8 @@ impl Sysopt {
|
|||||||
SYSOPT.get_or_init(|| Sysopt {
|
SYSOPT.get_or_init(|| Sysopt {
|
||||||
cur_sysproxy: Arc::new(Mutex::new(None)),
|
cur_sysproxy: Arc::new(Mutex::new(None)),
|
||||||
old_sysproxy: Arc::new(Mutex::new(None)),
|
old_sysproxy: Arc::new(Mutex::new(None)),
|
||||||
|
cur_autoproxy: Arc::new(Mutex::new(None)),
|
||||||
|
old_autoproxy: Arc::new(Mutex::new(None)),
|
||||||
auto_launch: Arc::new(Mutex::new(None)),
|
auto_launch: Arc::new(Mutex::new(None)),
|
||||||
guard_state: Arc::new(TokioMutex::new(false)),
|
guard_state: Arc::new(TokioMutex::new(false)),
|
||||||
})
|
})
|
||||||
@@ -49,17 +61,18 @@ impl Sysopt {
|
|||||||
.latest()
|
.latest()
|
||||||
.verge_mixed_port
|
.verge_mixed_port
|
||||||
.unwrap_or(Config::clash().data().get_mixed_port());
|
.unwrap_or(Config::clash().data().get_mixed_port());
|
||||||
|
let pac_port = IVerge::get_singleton_port();
|
||||||
|
|
||||||
let (enable, bypass) = {
|
let (enable, bypass, pac) = {
|
||||||
let verge = Config::verge();
|
let verge = Config::verge();
|
||||||
let verge = verge.latest();
|
let verge = verge.latest();
|
||||||
(
|
(
|
||||||
verge.enable_system_proxy.unwrap_or(false),
|
verge.enable_system_proxy.unwrap_or(false),
|
||||||
verge.system_proxy_bypass.clone(),
|
verge.system_proxy_bypass.clone(),
|
||||||
|
verge.proxy_auto_config.unwrap_or(false),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
let mut sys = Sysproxy {
|
||||||
let current = Sysproxy {
|
|
||||||
enable,
|
enable,
|
||||||
host: String::from("127.0.0.1"),
|
host: String::from("127.0.0.1"),
|
||||||
port,
|
port,
|
||||||
@@ -74,13 +87,32 @@ impl Sysopt {
|
|||||||
None => DEFAULT_BYPASS.into(),
|
None => DEFAULT_BYPASS.into(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
let mut auto = Autoproxy {
|
||||||
if enable {
|
enable,
|
||||||
|
url: format!("http://127.0.0.1:{pac_port}/commands/pac"),
|
||||||
|
};
|
||||||
|
if pac {
|
||||||
|
sys.enable = false;
|
||||||
let old = Sysproxy::get_system_proxy().ok();
|
let old = Sysproxy::get_system_proxy().ok();
|
||||||
current.set_system_proxy()?;
|
sys.set_system_proxy()?;
|
||||||
|
|
||||||
*self.old_sysproxy.lock() = old;
|
*self.old_sysproxy.lock() = old;
|
||||||
*self.cur_sysproxy.lock() = Some(current);
|
*self.cur_sysproxy.lock() = Some(sys);
|
||||||
|
|
||||||
|
let old = Autoproxy::get_auto_proxy().ok();
|
||||||
|
auto.set_auto_proxy()?;
|
||||||
|
*self.old_autoproxy.lock() = old;
|
||||||
|
*self.cur_autoproxy.lock() = Some(auto);
|
||||||
|
} else {
|
||||||
|
auto.enable = false;
|
||||||
|
let old = Autoproxy::get_auto_proxy().ok();
|
||||||
|
auto.set_auto_proxy()?;
|
||||||
|
*self.old_autoproxy.lock() = old;
|
||||||
|
*self.cur_autoproxy.lock() = Some(auto);
|
||||||
|
|
||||||
|
let old = Sysproxy::get_system_proxy().ok();
|
||||||
|
sys.set_system_proxy()?;
|
||||||
|
*self.old_sysproxy.lock() = old;
|
||||||
|
*self.cur_sysproxy.lock() = Some(sys);
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the system proxy guard
|
// run the system proxy guard
|
||||||
@@ -92,24 +124,38 @@ impl Sysopt {
|
|||||||
pub fn update_sysproxy(&self) -> Result<()> {
|
pub fn update_sysproxy(&self) -> Result<()> {
|
||||||
let mut cur_sysproxy = self.cur_sysproxy.lock();
|
let mut cur_sysproxy = self.cur_sysproxy.lock();
|
||||||
let old_sysproxy = self.old_sysproxy.lock();
|
let old_sysproxy = self.old_sysproxy.lock();
|
||||||
|
let mut cur_autoproxy = self.cur_autoproxy.lock();
|
||||||
|
let old_autoproxy = self.old_autoproxy.lock();
|
||||||
|
|
||||||
if cur_sysproxy.is_none() || old_sysproxy.is_none() {
|
let (enable, bypass, pac) = {
|
||||||
drop(cur_sysproxy);
|
|
||||||
drop(old_sysproxy);
|
|
||||||
return self.init_sysproxy();
|
|
||||||
}
|
|
||||||
|
|
||||||
let (enable, bypass) = {
|
|
||||||
let verge = Config::verge();
|
let verge = Config::verge();
|
||||||
let verge = verge.latest();
|
let verge = verge.latest();
|
||||||
(
|
(
|
||||||
verge.enable_system_proxy.unwrap_or(false),
|
verge.enable_system_proxy.unwrap_or(false),
|
||||||
verge.system_proxy_bypass.clone(),
|
verge.system_proxy_bypass.clone(),
|
||||||
|
verge.proxy_auto_config.unwrap_or(false),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let mut sysproxy = cur_sysproxy.take().unwrap();
|
if pac {
|
||||||
|
if cur_autoproxy.is_none() || old_autoproxy.is_none() {
|
||||||
|
drop(cur_autoproxy);
|
||||||
|
drop(old_autoproxy);
|
||||||
|
return self.init_sysproxy();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if cur_sysproxy.is_none() || old_sysproxy.is_none() {
|
||||||
|
drop(cur_sysproxy);
|
||||||
|
drop(old_sysproxy);
|
||||||
|
return self.init_sysproxy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let port = Config::verge()
|
||||||
|
.latest()
|
||||||
|
.verge_mixed_port
|
||||||
|
.unwrap_or(Config::clash().data().get_mixed_port());
|
||||||
|
let pac_port = IVerge::get_singleton_port();
|
||||||
|
|
||||||
sysproxy.enable = enable;
|
let mut sysproxy = cur_sysproxy.take().unwrap();
|
||||||
sysproxy.bypass = match bypass {
|
sysproxy.bypass = match bypass {
|
||||||
Some(bypass) => {
|
Some(bypass) => {
|
||||||
if bypass.is_empty() {
|
if bypass.is_empty() {
|
||||||
@@ -120,15 +166,26 @@ impl Sysopt {
|
|||||||
}
|
}
|
||||||
None => DEFAULT_BYPASS.into(),
|
None => DEFAULT_BYPASS.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let port = Config::verge()
|
|
||||||
.latest()
|
|
||||||
.verge_mixed_port
|
|
||||||
.unwrap_or(Config::clash().data().get_mixed_port());
|
|
||||||
sysproxy.port = port;
|
sysproxy.port = port;
|
||||||
|
|
||||||
sysproxy.set_system_proxy()?;
|
let mut autoproxy = cur_autoproxy.take().unwrap();
|
||||||
*cur_sysproxy = Some(sysproxy);
|
autoproxy.url = format!("http://127.0.0.1:{pac_port}/commands/pac");
|
||||||
|
|
||||||
|
if pac {
|
||||||
|
sysproxy.enable = false;
|
||||||
|
sysproxy.set_system_proxy()?;
|
||||||
|
*cur_sysproxy = Some(sysproxy);
|
||||||
|
autoproxy.enable = enable;
|
||||||
|
autoproxy.set_auto_proxy()?;
|
||||||
|
*cur_autoproxy = Some(autoproxy);
|
||||||
|
} else {
|
||||||
|
autoproxy.enable = false;
|
||||||
|
autoproxy.set_auto_proxy()?;
|
||||||
|
*cur_autoproxy = Some(autoproxy);
|
||||||
|
sysproxy.enable = enable;
|
||||||
|
sysproxy.set_system_proxy()?;
|
||||||
|
*cur_sysproxy = Some(sysproxy);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -137,8 +194,11 @@ impl Sysopt {
|
|||||||
pub fn reset_sysproxy(&self) -> Result<()> {
|
pub fn reset_sysproxy(&self) -> Result<()> {
|
||||||
let mut cur_sysproxy = self.cur_sysproxy.lock();
|
let mut cur_sysproxy = self.cur_sysproxy.lock();
|
||||||
let mut old_sysproxy = self.old_sysproxy.lock();
|
let mut old_sysproxy = self.old_sysproxy.lock();
|
||||||
|
let mut cur_autoproxy = self.cur_autoproxy.lock();
|
||||||
|
let mut old_autoproxy = self.old_autoproxy.lock();
|
||||||
|
|
||||||
let cur_sysproxy = cur_sysproxy.take();
|
let cur_sysproxy = cur_sysproxy.take();
|
||||||
|
let cur_autoproxy = cur_autoproxy.take();
|
||||||
|
|
||||||
if let Some(mut old) = old_sysproxy.take() {
|
if let Some(mut old) = old_sysproxy.take() {
|
||||||
// 如果原代理和当前代理 端口一致,就disable关闭,否则就恢复原代理设置
|
// 如果原代理和当前代理 端口一致,就disable关闭,否则就恢复原代理设置
|
||||||
@@ -162,6 +222,28 @@ impl Sysopt {
|
|||||||
log::info!(target: "app", "reset proxy with no action");
|
log::info!(target: "app", "reset proxy with no action");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(mut old) = old_autoproxy.take() {
|
||||||
|
// 如果原代理和当前代理 URL一致,就disable关闭,否则就恢复原代理设置
|
||||||
|
// 当前没有设置代理的时候,不确定旧设置是否和当前一致,全关了
|
||||||
|
let url_same = cur_autoproxy.map_or(true, |cur| old.url == cur.url);
|
||||||
|
|
||||||
|
if old.enable && url_same {
|
||||||
|
old.enable = false;
|
||||||
|
log::info!(target: "app", "reset proxy by disabling the original proxy");
|
||||||
|
} else {
|
||||||
|
log::info!(target: "app", "reset proxy to the original proxy");
|
||||||
|
}
|
||||||
|
|
||||||
|
old.set_auto_proxy()?;
|
||||||
|
} else if let Some(mut cur @ Autoproxy { enable: true, .. }) = cur_autoproxy {
|
||||||
|
// 没有原代理,就按现在的代理设置disable即可
|
||||||
|
log::info!(target: "app", "reset proxy by disabling the current proxy");
|
||||||
|
cur.enable = false;
|
||||||
|
cur.set_auto_proxy()?;
|
||||||
|
} else {
|
||||||
|
log::info!(target: "app", "reset proxy with no action");
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,7 +349,7 @@ impl Sysopt {
|
|||||||
loop {
|
loop {
|
||||||
sleep(Duration::from_secs(wait_secs)).await;
|
sleep(Duration::from_secs(wait_secs)).await;
|
||||||
|
|
||||||
let (enable, guard, guard_duration, bypass) = {
|
let (enable, guard, guard_duration, bypass, pac) = {
|
||||||
let verge = Config::verge();
|
let verge = Config::verge();
|
||||||
let verge = verge.latest();
|
let verge = verge.latest();
|
||||||
(
|
(
|
||||||
@@ -275,6 +357,7 @@ impl Sysopt {
|
|||||||
verge.enable_proxy_guard.unwrap_or(false),
|
verge.enable_proxy_guard.unwrap_or(false),
|
||||||
verge.proxy_guard_duration.unwrap_or(10),
|
verge.proxy_guard_duration.unwrap_or(10),
|
||||||
verge.system_proxy_bypass.clone(),
|
verge.system_proxy_bypass.clone(),
|
||||||
|
verge.proxy_auto_config.unwrap_or(false),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -294,24 +377,32 @@ impl Sysopt {
|
|||||||
.verge_mixed_port
|
.verge_mixed_port
|
||||||
.unwrap_or(Config::clash().data().get_mixed_port())
|
.unwrap_or(Config::clash().data().get_mixed_port())
|
||||||
};
|
};
|
||||||
|
let pac_port = IVerge::get_singleton_port();
|
||||||
let sysproxy = Sysproxy {
|
if pac {
|
||||||
enable: true,
|
let autoproxy = Autoproxy {
|
||||||
host: "127.0.0.1".into(),
|
enable: true,
|
||||||
port,
|
url: format!("http://127.0.0.1:{pac_port}/commands/pac"),
|
||||||
bypass: match bypass {
|
};
|
||||||
Some(bypass) => {
|
log_err!(autoproxy.set_auto_proxy());
|
||||||
if bypass.is_empty() {
|
} else {
|
||||||
DEFAULT_BYPASS.into()
|
let sysproxy = Sysproxy {
|
||||||
} else {
|
enable: true,
|
||||||
bypass
|
host: "127.0.0.1".into(),
|
||||||
|
port,
|
||||||
|
bypass: match bypass {
|
||||||
|
Some(bypass) => {
|
||||||
|
if bypass.is_empty() {
|
||||||
|
DEFAULT_BYPASS.into()
|
||||||
|
} else {
|
||||||
|
bypass
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
None => DEFAULT_BYPASS.into(),
|
||||||
None => DEFAULT_BYPASS.into(),
|
},
|
||||||
},
|
};
|
||||||
};
|
|
||||||
|
|
||||||
log_err!(sysproxy.set_system_proxy());
|
log_err!(sysproxy.set_system_proxy());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut state = guard_state.lock().await;
|
let mut state = guard_state.lock().await;
|
||||||
|
@@ -177,6 +177,8 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
|
|||||||
let tun_mode = patch.enable_tun_mode;
|
let tun_mode = patch.enable_tun_mode;
|
||||||
let auto_launch = patch.enable_auto_launch;
|
let auto_launch = patch.enable_auto_launch;
|
||||||
let system_proxy = patch.enable_system_proxy;
|
let system_proxy = patch.enable_system_proxy;
|
||||||
|
let pac = patch.proxy_auto_config;
|
||||||
|
let pac_content = patch.pac_file_content;
|
||||||
let proxy_bypass = patch.system_proxy_bypass;
|
let proxy_bypass = patch.system_proxy_bypass;
|
||||||
let language = patch.language;
|
let language = patch.language;
|
||||||
let port = patch.verge_mixed_port;
|
let port = patch.verge_mixed_port;
|
||||||
@@ -219,7 +221,12 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> {
|
|||||||
if auto_launch.is_some() {
|
if auto_launch.is_some() {
|
||||||
sysopt::Sysopt::global().update_launch()?;
|
sysopt::Sysopt::global().update_launch()?;
|
||||||
}
|
}
|
||||||
if system_proxy.is_some() || proxy_bypass.is_some() || port.is_some() {
|
if system_proxy.is_some()
|
||||||
|
|| proxy_bypass.is_some()
|
||||||
|
|| port.is_some()
|
||||||
|
|| pac.is_some()
|
||||||
|
|| pac_content.is_some()
|
||||||
|
{
|
||||||
sysopt::Sysopt::global().update_sysproxy()?;
|
sysopt::Sysopt::global().update_sysproxy()?;
|
||||||
sysopt::Sysopt::global().guard_proxy();
|
sysopt::Sysopt::global().guard_proxy();
|
||||||
}
|
}
|
||||||
|
@@ -36,6 +36,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
// common
|
// common
|
||||||
cmds::get_sys_proxy,
|
cmds::get_sys_proxy,
|
||||||
|
cmds::get_auto_proxy,
|
||||||
cmds::open_app_dir,
|
cmds::open_app_dir,
|
||||||
cmds::open_logs_dir,
|
cmds::open_logs_dir,
|
||||||
cmds::open_web_url,
|
cmds::open_web_url,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
extern crate warp;
|
extern crate warp;
|
||||||
|
|
||||||
use super::resolve;
|
use super::resolve;
|
||||||
use crate::config::IVerge;
|
use crate::config::{Config, IVerge, DEFAULT_PAC};
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
use port_scanner::local_port_available;
|
use port_scanner::local_port_available;
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
@@ -64,6 +64,22 @@ pub fn embed_server(app_handle: AppHandle) {
|
|||||||
"ok"
|
"ok"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let pac = warp::path!("commands" / "pac").map(move || {
|
||||||
|
let content = Config::verge()
|
||||||
|
.latest()
|
||||||
|
.pac_file_content
|
||||||
|
.clone()
|
||||||
|
.unwrap_or(DEFAULT_PAC.to_string());
|
||||||
|
let port = Config::verge()
|
||||||
|
.latest()
|
||||||
|
.verge_mixed_port
|
||||||
|
.unwrap_or(Config::clash().data().get_mixed_port());
|
||||||
|
let content = content.replace("%mixed-port%", &format!("{}", port));
|
||||||
|
warp::http::Response::builder()
|
||||||
|
.header("Content-Type", "application/x-ns-proxy-autoconfig")
|
||||||
|
.body(content)
|
||||||
|
.unwrap_or_default()
|
||||||
|
});
|
||||||
let scheme = warp::path!("commands" / "scheme")
|
let scheme = warp::path!("commands" / "scheme")
|
||||||
.and(warp::query::<QueryParam>())
|
.and(warp::query::<QueryParam>())
|
||||||
.and_then(scheme_handler);
|
.and_then(scheme_handler);
|
||||||
@@ -72,7 +88,7 @@ pub fn embed_server(app_handle: AppHandle) {
|
|||||||
resolve::resolve_scheme(query.param).await;
|
resolve::resolve_scheme(query.param).await;
|
||||||
Ok("ok")
|
Ok("ok")
|
||||||
}
|
}
|
||||||
let commands = ping.or(visible).or(scheme);
|
let commands = ping.or(visible).or(pac).or(scheme);
|
||||||
warp::serve(commands).run(([127, 0, 0, 1], port)).await;
|
warp::serve(commands).run(([127, 0, 0, 1], port)).await;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
"$schema": "../node_modules/@tauri-apps/cli/schema.json",
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "Clash Verge",
|
"productName": "Clash Verge",
|
||||||
"version": "1.6.2"
|
"version": "1.6.4"
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"distDir": "../dist",
|
"distDir": "../dist",
|
||||||
@@ -38,10 +38,6 @@
|
|||||||
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEQyOEMyRjBCQkVGOUJEREYKUldUZnZmbStDeStNMHU5Mmo1N24xQXZwSVRYbXA2NUpzZE5oVzlqeS9Bc0t6RVV4MmtwVjBZaHgK"
|
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEQyOEMyRjBCQkVGOUJEREYKUldUZnZmbStDeStNMHU5Mmo1N24xQXZwSVRYbXA2NUpzZE5oVzlqeS9Bc0t6RVV4MmtwVjBZaHgK"
|
||||||
},
|
},
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
"http": {
|
|
||||||
"all": true,
|
|
||||||
"scope": ["http://**", "http://**"]
|
|
||||||
},
|
|
||||||
"shell": {
|
"shell": {
|
||||||
"all": true
|
"all": true
|
||||||
},
|
},
|
||||||
|
@@ -36,6 +36,7 @@ export const LayoutControl = () => {
|
|||||||
<ButtonGroup
|
<ButtonGroup
|
||||||
variant="text"
|
variant="text"
|
||||||
sx={{
|
sx={{
|
||||||
|
zIndex: 1000,
|
||||||
height: "100%",
|
height: "100%",
|
||||||
".MuiButtonGroup-grouped": {
|
".MuiButtonGroup-grouped": {
|
||||||
borderRadius: "0px",
|
borderRadius: "0px",
|
||||||
|
@@ -57,6 +57,23 @@ configureMonacoYaml(monaco, {
|
|||||||
});
|
});
|
||||||
// PAC definition
|
// PAC definition
|
||||||
monaco.languages.typescript.javascriptDefaults.addExtraLib(pac, "pac.d.ts");
|
monaco.languages.typescript.javascriptDefaults.addExtraLib(pac, "pac.d.ts");
|
||||||
|
monaco.languages.registerCompletionItemProvider("javascript", {
|
||||||
|
provideCompletionItems: (model, position) => ({
|
||||||
|
suggestions: [
|
||||||
|
{
|
||||||
|
label: "%mixed-port%",
|
||||||
|
kind: monaco.languages.CompletionItemKind.Text,
|
||||||
|
insertText: "%mixed-port%",
|
||||||
|
range: {
|
||||||
|
startLineNumber: position.lineNumber,
|
||||||
|
endLineNumber: position.lineNumber,
|
||||||
|
startColumn: model.getWordUntilPosition(position).startColumn - 1,
|
||||||
|
endColumn: model.getWordUntilPosition(position).endColumn - 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
export const EditorViewer = (props: Props) => {
|
export const EditorViewer = (props: Props) => {
|
||||||
const {
|
const {
|
||||||
@@ -114,7 +131,7 @@ export const EditorViewer = (props: Props) => {
|
|||||||
padding: {
|
padding: {
|
||||||
top: 33, // 顶部padding防止遮挡snippets
|
top: 33, // 顶部padding防止遮挡snippets
|
||||||
},
|
},
|
||||||
fontFamily: `Fira Code, Roboto Mono, Roboto, Source Code Pro, Menlo, Monaco, Consolas, Courier New, monospace, "Apple Color Emoji"${
|
fontFamily: `Fira Code, JetBrains Mono, Roboto Mono, "Source Code Pro", Consolas, Menlo, Monaco, monospace, "Courier New", "Apple Color Emoji"${
|
||||||
getSystem() === "windows" ? ", twemoji mozilla" : ""
|
getSystem() === "windows" ? ", twemoji mozilla" : ""
|
||||||
}`,
|
}`,
|
||||||
fontLigatures: true, // 连字符
|
fontLigatures: true, // 连字符
|
||||||
|
@@ -10,23 +10,34 @@ import {
|
|||||||
styled,
|
styled,
|
||||||
TextField,
|
TextField,
|
||||||
Typography,
|
Typography,
|
||||||
|
Button,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { useVerge } from "@/hooks/use-verge";
|
import { useVerge } from "@/hooks/use-verge";
|
||||||
import { getSystemProxy } from "@/services/cmds";
|
import { getSystemProxy, getAutotemProxy } from "@/services/cmds";
|
||||||
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
|
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
|
||||||
|
import { Edit } from "@mui/icons-material";
|
||||||
|
import { EditorViewer } from "@/components/profile/editor-viewer";
|
||||||
|
const DEFAULT_PAC = `function FindProxyForURL(url, host) {
|
||||||
|
return "PROXY 127.0.0.1:%mixed-port%; SOCKS5 127.0.0.1:%mixed-port%; DIRECT;";
|
||||||
|
}`;
|
||||||
|
|
||||||
export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const [editorOpen, setEditorOpen] = useState(false);
|
||||||
const { verge, patchVerge } = useVerge();
|
const { verge, patchVerge } = useVerge();
|
||||||
|
|
||||||
type SysProxy = Awaited<ReturnType<typeof getSystemProxy>>;
|
type SysProxy = Awaited<ReturnType<typeof getSystemProxy>>;
|
||||||
const [sysproxy, setSysproxy] = useState<SysProxy>();
|
const [sysproxy, setSysproxy] = useState<SysProxy>();
|
||||||
|
|
||||||
|
type AutoProxy = Awaited<ReturnType<typeof getAutotemProxy>>;
|
||||||
|
const [autoproxy, setAutoproxy] = useState<AutoProxy>();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
enable_system_proxy: enabled,
|
enable_system_proxy: enabled,
|
||||||
|
proxy_auto_config,
|
||||||
|
pac_file_content,
|
||||||
enable_proxy_guard,
|
enable_proxy_guard,
|
||||||
system_proxy_bypass,
|
system_proxy_bypass,
|
||||||
proxy_guard_duration,
|
proxy_guard_duration,
|
||||||
@@ -36,6 +47,8 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
guard: enable_proxy_guard,
|
guard: enable_proxy_guard,
|
||||||
bypass: system_proxy_bypass,
|
bypass: system_proxy_bypass,
|
||||||
duration: proxy_guard_duration ?? 10,
|
duration: proxy_guard_duration ?? 10,
|
||||||
|
pac: proxy_auto_config,
|
||||||
|
pac_content: pac_file_content ?? DEFAULT_PAC,
|
||||||
});
|
});
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
@@ -45,8 +58,11 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
guard: enable_proxy_guard,
|
guard: enable_proxy_guard,
|
||||||
bypass: system_proxy_bypass,
|
bypass: system_proxy_bypass,
|
||||||
duration: proxy_guard_duration ?? 10,
|
duration: proxy_guard_duration ?? 10,
|
||||||
|
pac: proxy_auto_config,
|
||||||
|
pac_content: pac_file_content ?? DEFAULT_PAC,
|
||||||
});
|
});
|
||||||
getSystemProxy().then((p) => setSysproxy(p));
|
getSystemProxy().then((p) => setSysproxy(p));
|
||||||
|
getAutotemProxy().then((p) => setAutoproxy(p));
|
||||||
},
|
},
|
||||||
close: () => setOpen(false),
|
close: () => setOpen(false),
|
||||||
}));
|
}));
|
||||||
@@ -68,6 +84,12 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
if (value.bypass !== system_proxy_bypass) {
|
if (value.bypass !== system_proxy_bypass) {
|
||||||
patch.system_proxy_bypass = value.bypass;
|
patch.system_proxy_bypass = value.bypass;
|
||||||
}
|
}
|
||||||
|
if (value.pac !== proxy_auto_config) {
|
||||||
|
patch.proxy_auto_config = value.pac;
|
||||||
|
}
|
||||||
|
if (value.pac_content !== pac_file_content) {
|
||||||
|
patch.pac_file_content = value.pac_content;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await patchVerge(patch);
|
await patchVerge(patch);
|
||||||
@@ -89,6 +111,15 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
onOk={onSave}
|
onOk={onSave}
|
||||||
>
|
>
|
||||||
<List>
|
<List>
|
||||||
|
<ListItem sx={{ padding: "5px 2px" }}>
|
||||||
|
<ListItemText primary={t("Use PAC Mode")} />
|
||||||
|
<Switch
|
||||||
|
edge="end"
|
||||||
|
disabled={!enabled}
|
||||||
|
checked={value.pac}
|
||||||
|
onChange={(_, e) => setValue((v) => ({ ...v, pac: e }))}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
<ListItem sx={{ padding: "5px 2px" }}>
|
<ListItem sx={{ padding: "5px 2px" }}>
|
||||||
<ListItemText primary={t("Proxy Guard")} />
|
<ListItemText primary={t("Proxy Guard")} />
|
||||||
<Switch
|
<Switch
|
||||||
@@ -117,25 +148,67 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
{!value.pac && (
|
||||||
<ListItem sx={{ padding: "5px 2px", alignItems: "start" }}>
|
<>
|
||||||
<ListItemText primary={t("Proxy Bypass")} sx={{ padding: "3px 0" }} />
|
<ListItem sx={{ padding: "5px 2px", alignItems: "start" }}>
|
||||||
</ListItem>
|
<ListItemText
|
||||||
<ListItem sx={{ padding: "5px 2px" }}>
|
primary={t("Proxy Bypass")}
|
||||||
<TextField
|
sx={{ padding: "3px 0" }}
|
||||||
disabled={!enabled}
|
/>
|
||||||
size="small"
|
</ListItem>
|
||||||
autoComplete="off"
|
<ListItem sx={{ padding: "5px 2px" }}>
|
||||||
multiline
|
<TextField
|
||||||
rows={4}
|
disabled={!enabled}
|
||||||
sx={{ width: "100%" }}
|
size="small"
|
||||||
value={value.bypass}
|
autoComplete="off"
|
||||||
placeholder={sysproxy?.bypass || `-`}
|
multiline
|
||||||
onChange={(e) =>
|
rows={4}
|
||||||
setValue((v) => ({ ...v, bypass: e.target.value }))
|
sx={{ width: "100%" }}
|
||||||
}
|
value={value.bypass}
|
||||||
/>
|
placeholder={sysproxy?.bypass || `-`}
|
||||||
</ListItem>
|
onChange={(e) =>
|
||||||
|
setValue((v) => ({ ...v, bypass: e.target.value }))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{value.pac && (
|
||||||
|
<>
|
||||||
|
<ListItem sx={{ padding: "5px 2px", alignItems: "start" }}>
|
||||||
|
<ListItemText
|
||||||
|
primary={t("PAC Script Content")}
|
||||||
|
sx={{ padding: "3px 0" }}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
startIcon={<Edit />}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={() => {
|
||||||
|
setEditorOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("Edit")} PAC
|
||||||
|
</Button>
|
||||||
|
<EditorViewer
|
||||||
|
title={`${t("Edit")} PAC`}
|
||||||
|
mode="text"
|
||||||
|
property={value.pac_content ?? ""}
|
||||||
|
open={editorOpen}
|
||||||
|
language="javascript"
|
||||||
|
onChange={(content) => {
|
||||||
|
let pac = DEFAULT_PAC;
|
||||||
|
if (content && content.trim().length > 0) {
|
||||||
|
pac = content;
|
||||||
|
}
|
||||||
|
setValue((v) => ({ ...v, pac_content: pac }));
|
||||||
|
}}
|
||||||
|
onClose={() => {
|
||||||
|
setEditorOpen(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ListItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</List>
|
</List>
|
||||||
|
|
||||||
<Box sx={{ mt: 2.5 }}>
|
<Box sx={{ mt: 2.5 }}>
|
||||||
@@ -146,29 +219,42 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||||||
<FlexBox>
|
<FlexBox>
|
||||||
<Typography className="label">{t("Enable status")}</Typography>
|
<Typography className="label">{t("Enable status")}</Typography>
|
||||||
<Typography className="value">
|
<Typography className="value">
|
||||||
{(!!sysproxy?.enable).toString()}
|
{value.pac
|
||||||
|
? (!!autoproxy?.enable).toString()
|
||||||
|
: (!!sysproxy?.enable).toString()}
|
||||||
</Typography>
|
</Typography>
|
||||||
</FlexBox>
|
</FlexBox>
|
||||||
|
{!value.pac && (
|
||||||
|
<>
|
||||||
|
<FlexBox>
|
||||||
|
<Typography className="label">{t("Server Addr")}</Typography>
|
||||||
|
<Typography className="value">
|
||||||
|
{sysproxy?.server || "-"}
|
||||||
|
</Typography>
|
||||||
|
</FlexBox>
|
||||||
|
|
||||||
<FlexBox>
|
<FlexBox>
|
||||||
<Typography className="label">{t("Server Addr")}</Typography>
|
<Typography className="label">{t("Bypass")}</Typography>
|
||||||
<Typography className="value">{sysproxy?.server || "-"}</Typography>
|
</FlexBox>
|
||||||
</FlexBox>
|
<FlexBox>
|
||||||
|
<TextField
|
||||||
<FlexBox>
|
disabled={true}
|
||||||
<Typography className="label">{t("Bypass")}</Typography>
|
size="small"
|
||||||
</FlexBox>
|
autoComplete="off"
|
||||||
<FlexBox>
|
multiline
|
||||||
<TextField
|
rows={4}
|
||||||
disabled={true}
|
sx={{ width: "100%" }}
|
||||||
size="small"
|
value={sysproxy?.bypass || "-"}
|
||||||
autoComplete="off"
|
/>
|
||||||
multiline
|
</FlexBox>
|
||||||
rows={4}
|
</>
|
||||||
sx={{ width: "100%" }}
|
)}
|
||||||
value={sysproxy?.bypass || "-"}
|
{value.pac && (
|
||||||
/>
|
<FlexBox>
|
||||||
</FlexBox>
|
<Typography className="label">{t("PAC URL")}</Typography>
|
||||||
|
<Typography className="value">{autoproxy?.url || "-"}</Typography>
|
||||||
|
</FlexBox>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
);
|
);
|
||||||
|
@@ -118,6 +118,9 @@
|
|||||||
"System Proxy Setting": "System Proxy Setting",
|
"System Proxy Setting": "System Proxy Setting",
|
||||||
"Open UWP tool": "Open UWP tool",
|
"Open UWP tool": "Open UWP tool",
|
||||||
"Update GeoData": "Update GeoData",
|
"Update GeoData": "Update GeoData",
|
||||||
|
"Use PAC Mode": "Use PAC Mode",
|
||||||
|
"PAC URL": "PAC URL",
|
||||||
|
"PAC Script Content": "PAC Script Content",
|
||||||
"Proxy Guard": "Proxy Guard",
|
"Proxy Guard": "Proxy Guard",
|
||||||
"Guard Duration": "Guard Duration",
|
"Guard Duration": "Guard Duration",
|
||||||
"Proxy Bypass": "Proxy Bypass",
|
"Proxy Bypass": "Proxy Bypass",
|
||||||
|
@@ -118,6 +118,9 @@
|
|||||||
"System Proxy Setting": "تنظیمات پراکسی سیستم",
|
"System Proxy Setting": "تنظیمات پراکسی سیستم",
|
||||||
"Open UWP tool": "باز کردن ابزار UWP",
|
"Open UWP tool": "باز کردن ابزار UWP",
|
||||||
"Update GeoData": "بهروزرسانی GeoData",
|
"Update GeoData": "بهروزرسانی GeoData",
|
||||||
|
"Use PAC Mode": "استفاده از حالت PAC",
|
||||||
|
"PAC URL": "PAC URL",
|
||||||
|
"PAC Script Content": "محتوای اسکریپت PAC",
|
||||||
"Proxy Guard": "محافظ پراکسی",
|
"Proxy Guard": "محافظ پراکسی",
|
||||||
"Guard Duration": "مدت محافظت",
|
"Guard Duration": "مدت محافظت",
|
||||||
"Proxy Bypass": "دور زدن پراکسی",
|
"Proxy Bypass": "دور زدن پراکسی",
|
||||||
|
@@ -118,6 +118,9 @@
|
|||||||
"System Proxy Setting": "Настройка системного прокси",
|
"System Proxy Setting": "Настройка системного прокси",
|
||||||
"Open UWP tool": "Открыть UWP инструмент",
|
"Open UWP tool": "Открыть UWP инструмент",
|
||||||
"Update GeoData": "Обновление GeoData",
|
"Update GeoData": "Обновление GeoData",
|
||||||
|
"Use PAC Mode": "Используйте режим PAC.",
|
||||||
|
"PAC URL": "Адрес PAC",
|
||||||
|
"PAC Script Content": "Содержание сценария PAC",
|
||||||
"Proxy Guard": "Защита прокси",
|
"Proxy Guard": "Защита прокси",
|
||||||
"Guard Duration": "Период защиты",
|
"Guard Duration": "Период защиты",
|
||||||
"Proxy Bypass": "Игнорирование прокси",
|
"Proxy Bypass": "Игнорирование прокси",
|
||||||
|
@@ -118,6 +118,9 @@
|
|||||||
"System Proxy Setting": "系统代理设置",
|
"System Proxy Setting": "系统代理设置",
|
||||||
"Open UWP tool": "UWP 工具",
|
"Open UWP tool": "UWP 工具",
|
||||||
"Update GeoData": "更新 GeoData",
|
"Update GeoData": "更新 GeoData",
|
||||||
|
"Use PAC Mode": "使用PAC模式",
|
||||||
|
"PAC URL": "PAC 地址",
|
||||||
|
"PAC Script Content": "PAC 脚本内容",
|
||||||
"Proxy Guard": "系统代理守卫",
|
"Proxy Guard": "系统代理守卫",
|
||||||
"Guard Duration": "代理守卫间隔",
|
"Guard Duration": "代理守卫间隔",
|
||||||
"Proxy Bypass": "代理绕过",
|
"Proxy Bypass": "代理绕过",
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import axiosTauriApiAdapter from "axios-tauri-api-adapter";
|
|
||||||
import axios, { AxiosInstance } from "axios";
|
import axios, { AxiosInstance } from "axios";
|
||||||
import { getClashInfo } from "./cmds";
|
import { getClashInfo } from "./cmds";
|
||||||
|
|
||||||
@@ -26,7 +25,6 @@ export const getAxios = async (force: boolean = false) => {
|
|||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
axiosIns = axios.create({
|
axiosIns = axios.create({
|
||||||
adapter: axiosTauriApiAdapter,
|
|
||||||
baseURL: `http://${server}`,
|
baseURL: `http://${server}`,
|
||||||
headers: secret ? { Authorization: `Bearer ${secret}` } : {},
|
headers: secret ? { Authorization: `Bearer ${secret}` } : {},
|
||||||
timeout: 15000,
|
timeout: 15000,
|
||||||
|
@@ -127,6 +127,13 @@ export async function getSystemProxy() {
|
|||||||
}>("get_sys_proxy");
|
}>("get_sys_proxy");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getAutotemProxy() {
|
||||||
|
return invoke<{
|
||||||
|
enable: boolean;
|
||||||
|
url: string;
|
||||||
|
}>("get_auto_proxy");
|
||||||
|
}
|
||||||
|
|
||||||
export async function changeClashCore(clashCore: string) {
|
export async function changeClashCore(clashCore: string) {
|
||||||
return invoke<any>("change_clash_core", { clashCore });
|
return invoke<any>("change_clash_core", { clashCore });
|
||||||
}
|
}
|
||||||
|
2
clash-verge-rev/src/services/types.d.ts
vendored
2
clash-verge-rev/src/services/types.d.ts
vendored
@@ -216,6 +216,8 @@ interface IVergeConfig {
|
|||||||
enable_service_mode?: boolean;
|
enable_service_mode?: boolean;
|
||||||
enable_silent_start?: boolean;
|
enable_silent_start?: boolean;
|
||||||
enable_system_proxy?: boolean;
|
enable_system_proxy?: boolean;
|
||||||
|
proxy_auto_config?: boolean;
|
||||||
|
pac_file_content?: string;
|
||||||
enable_random_port?: boolean;
|
enable_random_port?: boolean;
|
||||||
verge_mixed_port?: number;
|
verge_mixed_port?: number;
|
||||||
verge_socks_port?: number;
|
verge_socks_port?: number;
|
||||||
|
@@ -61,7 +61,8 @@ func (b *baseTransporter) RelayTCPConn(c net.Conn, handshakeF TCPHandShakeF) err
|
|||||||
ctx, c, buffer, constant.SniffTimeOut,
|
ctx, c, buffer, constant.SniffTimeOut,
|
||||||
sniff.TLSClientHello, sniff.HTTPHost)
|
sniff.TLSClientHello, sniff.HTTPHost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.l.Warnf("sniff error: %s", err)
|
// this mean no protocol sniffed
|
||||||
|
b.l.Debug("sniff error: %s", err)
|
||||||
}
|
}
|
||||||
if sniffMetadata != nil {
|
if sniffMetadata != nil {
|
||||||
b.l.Infof("sniffed protocol: %s", sniffMetadata.Protocol)
|
b.l.Infof("sniffed protocol: %s", sniffMetadata.Protocol)
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
LINUX_VERSION-5.10 = .217
|
LINUX_VERSION-5.10 = .218
|
||||||
LINUX_KERNEL_HASH-5.10.217 = c52bc1ffc396c11bce335c9ee5cd55fe4213cbc1fb4026ff62bb90c864c61f62
|
LINUX_KERNEL_HASH-5.10.218 = 9c36b243e8c3ec1d5963366618f336710b84340bf95be2037b26c452392cb2d6
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
LINUX_VERSION-5.15 = .159
|
LINUX_VERSION-5.15 = .160
|
||||||
LINUX_KERNEL_HASH-5.15.159 = 3478fe50225e9c88e09cf114f38e3fb71e82d9fdcc356aa1257d721199b341c5
|
LINUX_KERNEL_HASH-5.15.160 = f41e718e33b88f269a6b6a7653e5e9824c4ba541f6ffe5bf26ecc37c540a1b05
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
LINUX_VERSION-5.4 = .276
|
LINUX_VERSION-5.4 = .277
|
||||||
LINUX_KERNEL_HASH-5.4.276 = e2712ebd4421ffa5b25a366659ecfbe1b45a444027ee2fe57369676453e86e07
|
LINUX_KERNEL_HASH-5.4.277 = 7e1f5b28588e49ddfd18e7772476e4e8b52bdc9c3e19beafcbb7c103e6c01f51
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
LINUX_VERSION-6.1 = .91
|
LINUX_VERSION-6.1 = .92
|
||||||
LINUX_KERNEL_HASH-6.1.91 = 880ace63ca2291b8b639e9bd862cc828649d3e1e00ccfee5861473debd2e4dec
|
LINUX_KERNEL_HASH-6.1.92 = 9019f427bfdc9ced5bc954d760d37ac08c0cdffb45ad28087fc45a73e64336c9
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
LINUX_VERSION-6.6 = .31
|
LINUX_VERSION-6.6 = .32
|
||||||
LINUX_KERNEL_HASH-6.6.31 = d6ecff966f8c95ec4cb3bb303904f757b7de6a6bcfef0d0771cb852158e61c20
|
LINUX_KERNEL_HASH-6.6.32 = aaa824eaf07f61911d22b75ff090a403c3dd0bd73e23933e0bba8b5971436ce1
|
||||||
|
@@ -23,6 +23,7 @@ PKG_LICENSE:=GPL-2.0
|
|||||||
PKG_CONFIG_DEPENDS += \
|
PKG_CONFIG_DEPENDS += \
|
||||||
CONFIG_SIGNED_PACKAGES CONFIG_TARGET_INIT_PATH CONFIG_TARGET_PREINIT_DISABLE_FAILSAFE \
|
CONFIG_SIGNED_PACKAGES CONFIG_TARGET_INIT_PATH CONFIG_TARGET_PREINIT_DISABLE_FAILSAFE \
|
||||||
CONFIG_NAND_SUPPORT \
|
CONFIG_NAND_SUPPORT \
|
||||||
|
CONFIG_LEGACY_SDCARD_SUPPORT \
|
||||||
CONFIG_EMMC_SUPPORT \
|
CONFIG_EMMC_SUPPORT \
|
||||||
CONFIG_CLEAN_IPKG \
|
CONFIG_CLEAN_IPKG \
|
||||||
CONFIG_PER_FEED_REPO \
|
CONFIG_PER_FEED_REPO \
|
||||||
@@ -125,6 +126,12 @@ ifeq ($(CONFIG_NAND_SUPPORT),)
|
|||||||
endef
|
endef
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_LEGACY_SDCARD_SUPPORT),)
|
||||||
|
define Package/base-files/legacy-sdcard-support
|
||||||
|
rm -f $(1)/lib/upgrade/legacy-sdcard.sh
|
||||||
|
endef
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_EMMC_SUPPORT),)
|
ifeq ($(CONFIG_EMMC_SUPPORT),)
|
||||||
define Package/base-files/emmc-support
|
define Package/base-files/emmc-support
|
||||||
rm -f $(1)/lib/upgrade/emmc.sh
|
rm -f $(1)/lib/upgrade/emmc.sh
|
||||||
@@ -135,6 +142,7 @@ define Package/base-files/install
|
|||||||
$(CP) ./files/* $(1)/
|
$(CP) ./files/* $(1)/
|
||||||
$(Package/base-files/install-key)
|
$(Package/base-files/install-key)
|
||||||
$(Package/base-files/nand-support)
|
$(Package/base-files/nand-support)
|
||||||
|
$(Package/base-files/legacy-sdcard-support)
|
||||||
$(Package/base-files/emmc-support)
|
$(Package/base-files/emmc-support)
|
||||||
if [ -d $(GENERIC_PLATFORM_DIR)/base-files/. ]; then \
|
if [ -d $(GENERIC_PLATFORM_DIR)/base-files/. ]; then \
|
||||||
$(CP) $(GENERIC_PLATFORM_DIR)/base-files/* $(1)/; \
|
$(CP) $(GENERIC_PLATFORM_DIR)/base-files/* $(1)/; \
|
||||||
|
91
lede/package/base-files/files/lib/upgrade/legacy-sdcard.sh
Normal file
91
lede/package/base-files/files/lib/upgrade/legacy-sdcard.sh
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
legacy_sdcard_check_image() {
|
||||||
|
local file="$1"
|
||||||
|
local diskdev partdev diff
|
||||||
|
|
||||||
|
export_bootdevice && export_partdevice diskdev 0 || {
|
||||||
|
v "Unable to determine upgrade device"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get_partitions "/dev/$diskdev" bootdisk
|
||||||
|
|
||||||
|
v "Extract boot sector from the image"
|
||||||
|
get_image_dd "$1" of=/tmp/image.bs count=1 bs=512b
|
||||||
|
|
||||||
|
get_partitions /tmp/image.bs image
|
||||||
|
|
||||||
|
#compare tables
|
||||||
|
diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)"
|
||||||
|
|
||||||
|
rm -f /tmp/image.bs /tmp/partmap.bootdisk /tmp/partmap.image
|
||||||
|
|
||||||
|
if [ -n "$diff" ]; then
|
||||||
|
v "Partition layout has changed. Full image will be written."
|
||||||
|
ask_bool 0 "Abort" && exit 1
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
legacy_sdcard_do_upgrade() {
|
||||||
|
local board=$(board_name)
|
||||||
|
local diskdev partdev diff
|
||||||
|
|
||||||
|
export_bootdevice && export_partdevice diskdev 0 || {
|
||||||
|
v "Unable to determine upgrade device"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
sync
|
||||||
|
|
||||||
|
if [ "$UPGRADE_OPT_SAVE_PARTITIONS" = "1" ]; then
|
||||||
|
get_partitions "/dev/$diskdev" bootdisk
|
||||||
|
|
||||||
|
v "Extract boot sector from the image"
|
||||||
|
get_image_dd "$1" of=/tmp/image.bs count=1 bs=512b
|
||||||
|
|
||||||
|
get_partitions /tmp/image.bs image
|
||||||
|
|
||||||
|
#compare tables
|
||||||
|
diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)"
|
||||||
|
else
|
||||||
|
diff=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$diff" ]; then
|
||||||
|
get_image_dd "$1" of="/dev/$diskdev" bs=4096 conv=fsync
|
||||||
|
|
||||||
|
# Separate removal and addtion is necessary; otherwise, partition 1
|
||||||
|
# will be missing if it overlaps with the old partition 2
|
||||||
|
partx -d - "/dev/$diskdev"
|
||||||
|
partx -a - "/dev/$diskdev"
|
||||||
|
else
|
||||||
|
v "Writing bootloader to /dev/$diskdev"
|
||||||
|
get_image_dd "$1" of="$diskdev" bs=512 skip=1 seek=1 count=2048 conv=fsync
|
||||||
|
#iterate over each partition from the image and write it to the boot disk
|
||||||
|
while read part start size; do
|
||||||
|
if export_partdevice partdev $part; then
|
||||||
|
v "Writing image to /dev/$partdev..."
|
||||||
|
get_image_dd "$1" of="/dev/$partdev" ibs="512" obs=1M skip="$start" count="$size" conv=fsync
|
||||||
|
else
|
||||||
|
v "Unable to find partition $part device, skipped."
|
||||||
|
fi
|
||||||
|
done < /tmp/partmap.image
|
||||||
|
|
||||||
|
v "Writing new UUID to /dev/$diskdev..."
|
||||||
|
get_image_dd "$1" of="/dev/$diskdev" bs=1 skip=440 count=4 seek=440 conv=fsync
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
}
|
||||||
|
|
||||||
|
legacy_sdcard_copy_config() {
|
||||||
|
local partdev
|
||||||
|
|
||||||
|
if export_partdevice partdev 1; then
|
||||||
|
mkdir -p /boot
|
||||||
|
[ -f /boot/kernel.img ] || mount -o rw,noatime /dev/$partdev /boot
|
||||||
|
cp -af "$UPGRADE_BACKUP" "/boot/$BACKUP_FILE"
|
||||||
|
sync
|
||||||
|
umount /boot
|
||||||
|
fi
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
--- a/wpa_supplicant/Makefile
|
||||||
|
+++ b/wpa_supplicant/Makefile
|
||||||
|
@@ -339,6 +339,7 @@
|
||||||
|
|
||||||
|
ifdef CONFIG_MBO
|
||||||
|
CONFIG_WNM=y
|
||||||
|
+NEED_GAS=y
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef CONFIG_WNM
|
@@ -1833,7 +1833,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
}
|
}
|
||||||
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
||||||
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
|
||||||
@@ -3467,10 +3467,11 @@ static int bcmgenet_probe(struct platfor
|
@@ -3478,10 +3478,11 @@ static int bcmgenet_probe(struct platfor
|
||||||
const struct of_device_id *of_id = NULL;
|
const struct of_device_id *of_id = NULL;
|
||||||
struct bcmgenet_priv *priv;
|
struct bcmgenet_priv *priv;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
@@ -1846,7 +1846,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
|
|
||||||
/* Up to GENET_MAX_MQ_CNT + 1 TX queues and RX queues */
|
/* Up to GENET_MAX_MQ_CNT + 1 TX queues and RX queues */
|
||||||
dev = alloc_etherdev_mqs(sizeof(*priv), GENET_MAX_MQ_CNT + 1,
|
dev = alloc_etherdev_mqs(sizeof(*priv), GENET_MAX_MQ_CNT + 1,
|
||||||
@@ -3497,14 +3498,15 @@ static int bcmgenet_probe(struct platfor
|
@@ -3508,14 +3509,15 @@ static int bcmgenet_probe(struct platfor
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dn) {
|
if (dn) {
|
||||||
@@ -1865,7 +1865,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv->base = devm_platform_ioremap_resource(pdev, 0);
|
priv->base = devm_platform_ioremap_resource(pdev, 0);
|
||||||
@@ -3517,7 +3519,6 @@ static int bcmgenet_probe(struct platfor
|
@@ -3529,7 +3531,6 @@ static int bcmgenet_probe(struct platfor
|
||||||
|
|
||||||
SET_NETDEV_DEV(dev, &pdev->dev);
|
SET_NETDEV_DEV(dev, &pdev->dev);
|
||||||
dev_set_drvdata(&pdev->dev, dev);
|
dev_set_drvdata(&pdev->dev, dev);
|
||||||
|
@@ -1,10 +1,6 @@
|
|||||||
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
|
|
||||||
index 59ec726b7c77..3f089abd6fc9 100644
|
|
||||||
--- a/crypto/asymmetric_keys/Kconfig
|
--- a/crypto/asymmetric_keys/Kconfig
|
||||||
+++ b/crypto/asymmetric_keys/Kconfig
|
+++ b/crypto/asymmetric_keys/Kconfig
|
||||||
@@ -13,10 +13,11 @@ if ASYMMETRIC_KEY_TYPE
|
@@ -15,6 +15,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
|
||||||
config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
|
|
||||||
tristate "Asymmetric public-key crypto algorithm subtype"
|
|
||||||
select MPILIB
|
select MPILIB
|
||||||
select CRYPTO_HASH_INFO
|
select CRYPTO_HASH_INFO
|
||||||
select CRYPTO_AKCIPHER
|
select CRYPTO_AKCIPHER
|
||||||
@@ -12,5 +8,3 @@ index 59ec726b7c77..3f089abd6fc9 100644
|
|||||||
select CRYPTO_HASH
|
select CRYPTO_HASH
|
||||||
help
|
help
|
||||||
This option provides support for asymmetric public key type handling.
|
This option provides support for asymmetric public key type handling.
|
||||||
If signature generation and/or verification are to be used,
|
|
||||||
appropriate hash algorithms (such as SHA-1) must be available.
|
|
||||||
|
@@ -37,7 +37,7 @@
|
|||||||
* CONFIG_CMDLINE is meant to be a default in case nothing else
|
* CONFIG_CMDLINE is meant to be a default in case nothing else
|
||||||
--- a/arch/arm64/Kconfig
|
--- a/arch/arm64/Kconfig
|
||||||
+++ b/arch/arm64/Kconfig
|
+++ b/arch/arm64/Kconfig
|
||||||
@@ -2240,6 +2240,14 @@ config CMDLINE_FORCE
|
@@ -2239,6 +2239,14 @@ config CMDLINE_FORCE
|
||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
@@ -7,9 +7,11 @@ board_config_update
|
|||||||
board=$(board_name)
|
board=$(board_name)
|
||||||
|
|
||||||
case "$board" in
|
case "$board" in
|
||||||
|
qnap,qhora-321|\
|
||||||
iei,puzzle-m901)
|
iei,puzzle-m901)
|
||||||
ucidef_set_led_netdev "wan" "WAN" "white:network" "eth0" "link"
|
ucidef_set_led_netdev "wan" "WAN" "white:network" "eth0" "link"
|
||||||
;;
|
;;
|
||||||
|
qnap,qhora-322|\
|
||||||
iei,puzzle-m902)
|
iei,puzzle-m902)
|
||||||
ucidef_set_led_netdev "wan" "WAN" "white:network" "eth2" "link"
|
ucidef_set_led_netdev "wan" "WAN" "white:network" "eth2" "link"
|
||||||
;;
|
;;
|
||||||
|
@@ -13,9 +13,11 @@ case "$board" in
|
|||||||
globalscale,mochabin)
|
globalscale,mochabin)
|
||||||
ucidef_set_interfaces_lan_wan "lan0 lan1 lan2 lan3" "eth0 eth2"
|
ucidef_set_interfaces_lan_wan "lan0 lan1 lan2 lan3" "eth0 eth2"
|
||||||
;;
|
;;
|
||||||
|
qnap,qhora-321|\
|
||||||
iei,puzzle-m901)
|
iei,puzzle-m901)
|
||||||
ucidef_set_interfaces_lan_wan "eth1 eth2 eth3 eth4 eth5" "eth0"
|
ucidef_set_interfaces_lan_wan "eth1 eth2 eth3 eth4 eth5" "eth0"
|
||||||
;;
|
;;
|
||||||
|
qnap,qhora-322|\
|
||||||
iei,puzzle-m902)
|
iei,puzzle-m902)
|
||||||
ucidef_set_interfaces_lan_wan "eth0 eth1 eth3 eth4 eth5 eth6 eth7 eth8" "eth2"
|
ucidef_set_interfaces_lan_wan "eth0 eth1 eth3 eth4 eth5 eth6 eth7 eth8" "eth2"
|
||||||
;;
|
;;
|
||||||
|
@@ -31,6 +31,8 @@ platform_do_upgrade_emmc() {
|
|||||||
|
|
||||||
v "Writing new UUID to /dev/$diskdev..."
|
v "Writing new UUID to /dev/$diskdev..."
|
||||||
get_image_dd "$1" of="/dev/$diskdev" bs=1 skip=440 count=4 seek=440 conv=fsync
|
get_image_dd "$1" of="/dev/$diskdev" bs=1 skip=440 count=4 seek=440 conv=fsync
|
||||||
|
|
||||||
|
mkfs.ext4 -F -L rootfs_data $(find_mmc_part rootfs_data)
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
}
|
}
|
||||||
|
@@ -10,6 +10,8 @@ REQUIRE_IMAGE_METADATA=1
|
|||||||
platform_check_image() {
|
platform_check_image() {
|
||||||
case "$(board_name)" in
|
case "$(board_name)" in
|
||||||
globalscale,mochabin|\
|
globalscale,mochabin|\
|
||||||
|
qnap,qhora-321|\
|
||||||
|
qnap,qhora-322|\
|
||||||
iei,puzzle-m901|\
|
iei,puzzle-m901|\
|
||||||
iei,puzzle-m902|\
|
iei,puzzle-m902|\
|
||||||
marvell,armada8040-mcbin-doubleshot|\
|
marvell,armada8040-mcbin-doubleshot|\
|
||||||
@@ -25,6 +27,8 @@ platform_check_image() {
|
|||||||
|
|
||||||
platform_do_upgrade() {
|
platform_do_upgrade() {
|
||||||
case "$(board_name)" in
|
case "$(board_name)" in
|
||||||
|
qnap,qhora-321|\
|
||||||
|
qnap,qhora-322|\
|
||||||
iei,puzzle-m901|\
|
iei,puzzle-m901|\
|
||||||
iei,puzzle-m902)
|
iei,puzzle-m902)
|
||||||
platform_do_upgrade_emmc "$1"
|
platform_do_upgrade_emmc "$1"
|
||||||
@@ -43,6 +47,8 @@ platform_do_upgrade() {
|
|||||||
platform_copy_config() {
|
platform_copy_config() {
|
||||||
case "$(board_name)" in
|
case "$(board_name)" in
|
||||||
globalscale,mochabin|\
|
globalscale,mochabin|\
|
||||||
|
qnap,qhora-321|\
|
||||||
|
qnap,qhora-322|\
|
||||||
iei,puzzle-m901|\
|
iei,puzzle-m901|\
|
||||||
iei,puzzle-m902|\
|
iei,puzzle-m902|\
|
||||||
marvell,armada8040-mcbin-doubleshot|\
|
marvell,armada8040-mcbin-doubleshot|\
|
||||||
|
@@ -0,0 +1,404 @@
|
|||||||
|
// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Marvell International Ltd.
|
||||||
|
*
|
||||||
|
* Device tree for the CN9131-DB board.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cn9130.dtsi"
|
||||||
|
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
#include <dt-bindings/input/input.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
model = "QNAP QHora-321";
|
||||||
|
compatible = "qnap,qhora-321",
|
||||||
|
"marvell,armada-ap807-quad", "marvell,armada-ap807";
|
||||||
|
|
||||||
|
chosen {
|
||||||
|
stdout-path = "serial0:115200n8";
|
||||||
|
bootargs-append = " root=/dev/mmcblk0p3";
|
||||||
|
};
|
||||||
|
|
||||||
|
aliases {
|
||||||
|
i2c0 = &cp1_i2c0;
|
||||||
|
i2c1 = &cp0_i2c0;
|
||||||
|
ethernet0 = &cp0_eth0;
|
||||||
|
ethernet1 = &cp0_eth1;
|
||||||
|
ethernet2 = &cp0_eth2;
|
||||||
|
ethernet3 = &cp1_eth0;
|
||||||
|
ethernet4 = &cp1_eth1;
|
||||||
|
ethernet5 = &cp1_eth2;
|
||||||
|
gpio1 = &cp0_gpio1;
|
||||||
|
gpio2 = &cp0_gpio2;
|
||||||
|
gpio3 = &cp1_gpio1;
|
||||||
|
gpio4 = &cp1_gpio2;
|
||||||
|
led-boot = &led_power;
|
||||||
|
led-failsafe = &led_info;
|
||||||
|
led-running = &led_power;
|
||||||
|
led-upgrade = &led_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
memory@00000000 {
|
||||||
|
device_type = "memory";
|
||||||
|
reg = <0x0 0x0 0x0 0x80000000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
gpio_keys {
|
||||||
|
compatible = "gpio-keys";
|
||||||
|
|
||||||
|
reset {
|
||||||
|
label = "Reset";
|
||||||
|
linux,code = <KEY_RESTART>;
|
||||||
|
gpios = <&cp0_gpio2 4 GPIO_ACTIVE_LOW>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&uart0 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_uart0 {
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
puzzle-mcu {
|
||||||
|
compatible = "iei,wt61p803-puzzle";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
current-speed = <115200>;
|
||||||
|
enable-beep;
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
leds {
|
||||||
|
compatible = "iei,wt61p803-puzzle-leds";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
led@0 {
|
||||||
|
reg = <0>;
|
||||||
|
label = "white:network";
|
||||||
|
active-low;
|
||||||
|
};
|
||||||
|
|
||||||
|
led@1 {
|
||||||
|
reg = <1>;
|
||||||
|
label = "green:cloud";
|
||||||
|
active-low;
|
||||||
|
};
|
||||||
|
|
||||||
|
led_info: led@2 {
|
||||||
|
reg = <2>;
|
||||||
|
label = "orange:info";
|
||||||
|
active-low;
|
||||||
|
};
|
||||||
|
|
||||||
|
led_power: led@3 {
|
||||||
|
reg = <3>;
|
||||||
|
label = "yellow:power";
|
||||||
|
active-low;
|
||||||
|
default-state = "on";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
hwmon {
|
||||||
|
compatible = "iei,wt61p803-puzzle-hwmon";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
chassis_fan_group0: fan-group@0 {
|
||||||
|
#cooling-cells = <2>;
|
||||||
|
reg = <0x00>;
|
||||||
|
cooling-levels = <64 102 170 230 250>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&ap_thermal_cpu1 {
|
||||||
|
trips {
|
||||||
|
cpu_active: cpu-active {
|
||||||
|
temperature = <44000>;
|
||||||
|
hysteresis = <2000>;
|
||||||
|
type = "active";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
cooling-maps {
|
||||||
|
fan-map {
|
||||||
|
trip = <&cpu_active>;
|
||||||
|
cooling-device = <&chassis_fan_group0 64 THERMAL_NO_LIMIT>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* on-board eMMC - U9 */
|
||||||
|
&ap_sdhci0 {
|
||||||
|
pinctrl-names = "default";
|
||||||
|
bus-width = <8>;
|
||||||
|
status = "okay";
|
||||||
|
mmc-ddr-1_8v;
|
||||||
|
mmc-hs400-1_8v;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_crypto {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_xmdio {
|
||||||
|
status = "okay";
|
||||||
|
cp0_nbaset_phy0: ethernet-phy@0 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <2>;
|
||||||
|
};
|
||||||
|
cp0_nbaset_phy1: ethernet-phy@1 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <0>;
|
||||||
|
};
|
||||||
|
cp0_nbaset_phy2: ethernet-phy@2 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <8>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_ethernet {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SLM-1521-V2, CON9 */
|
||||||
|
&cp0_eth0 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "2500base-x";
|
||||||
|
phys = <&cp0_comphy2 0>;
|
||||||
|
phy = <&cp0_nbaset_phy0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_eth1 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "2500base-x";
|
||||||
|
phys = <&cp0_comphy4 1>;
|
||||||
|
phy = <&cp0_nbaset_phy1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_eth2 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "2500base-x";
|
||||||
|
phys = <&cp0_comphy5 2>;
|
||||||
|
phy = <&cp0_nbaset_phy2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_gpio1 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_gpio2 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_i2c0 {
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&cp0_i2c0_pins>;
|
||||||
|
status = "okay";
|
||||||
|
clock-frequency = <100000>;
|
||||||
|
rtc@32 {
|
||||||
|
compatible = "epson,rx8130";
|
||||||
|
reg = <0x32>;
|
||||||
|
wakeup-source;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SLM-1521-V2, CON6 */
|
||||||
|
&cp0_pcie0 {
|
||||||
|
status = "okay";
|
||||||
|
num-lanes = <2>;
|
||||||
|
num-viewport = <8>;
|
||||||
|
phys = <&cp0_comphy0 0>, <&cp0_comphy1 0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* U55 */
|
||||||
|
&cp0_spi1 {
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&cp0_spi0_pins>;
|
||||||
|
reg = <0x700680 0x50>, /* control */
|
||||||
|
<0x2000000 0x1000000>; /* CS0 */
|
||||||
|
status = "okay";
|
||||||
|
spi-flash@0 {
|
||||||
|
#address-cells = <0x1>;
|
||||||
|
#size-cells = <0x1>;
|
||||||
|
compatible = "jedec,spi-nor";
|
||||||
|
reg = <0x0>;
|
||||||
|
spi-max-frequency = <40000000>;
|
||||||
|
partitions {
|
||||||
|
compatible = "fixed-partitions";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
partition@0 {
|
||||||
|
label = "U-Boot";
|
||||||
|
reg = <0x0 0x1f0000>;
|
||||||
|
};
|
||||||
|
partition@1f0000 {
|
||||||
|
label = "U-Boot ENV Factory";
|
||||||
|
reg = <0x1f0000 0x10000>;
|
||||||
|
};
|
||||||
|
partition@200000 {
|
||||||
|
label = "Reserved";
|
||||||
|
reg = <0x200000 0x1f0000>;
|
||||||
|
};
|
||||||
|
partition@3f0000 {
|
||||||
|
label = "U-Boot ENV";
|
||||||
|
reg = <0x3f0000 0x10000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_syscon0 {
|
||||||
|
cp0_pinctrl: pinctrl {
|
||||||
|
compatible = "marvell,cp115-standalone-pinctrl";
|
||||||
|
cp0_i2c0_pins: cp0-i2c-pins-0 {
|
||||||
|
marvell,pins = "mpp37", "mpp38";
|
||||||
|
marvell,function = "i2c0";
|
||||||
|
};
|
||||||
|
cp0_i2c1_pins: cp0-i2c-pins-1 {
|
||||||
|
marvell,pins = "mpp35", "mpp36";
|
||||||
|
marvell,function = "i2c1";
|
||||||
|
};
|
||||||
|
cp0_ge1_rgmii_pins: cp0-ge-rgmii-pins-0 {
|
||||||
|
marvell,pins = "mpp0", "mpp1", "mpp2",
|
||||||
|
"mpp3", "mpp4", "mpp5",
|
||||||
|
"mpp6", "mpp7", "mpp8",
|
||||||
|
"mpp9", "mpp10", "mpp11";
|
||||||
|
marvell,function = "ge0";
|
||||||
|
};
|
||||||
|
cp0_ge2_rgmii_pins: cp0-ge-rgmii-pins-1 {
|
||||||
|
marvell,pins = "mpp44", "mpp45", "mpp46",
|
||||||
|
"mpp47", "mpp48", "mpp49",
|
||||||
|
"mpp50", "mpp51", "mpp52",
|
||||||
|
"mpp53", "mpp54", "mpp55";
|
||||||
|
marvell,function = "ge1";
|
||||||
|
};
|
||||||
|
cp0_spi0_pins: cp0-spi-pins-0 {
|
||||||
|
marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
|
||||||
|
marvell,function = "spi1";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instantiate the first connected CP115
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CP11X_NAME cp1
|
||||||
|
#define CP11X_BASE f6000000
|
||||||
|
#define CP11X_PCIEx_MEM_BASE(iface) (0xe2000000 + (iface * 0x1000000))
|
||||||
|
#define CP11X_PCIEx_MEM_SIZE(iface) 0xf00000
|
||||||
|
#define CP11X_PCIE0_BASE f6600000
|
||||||
|
#define CP11X_PCIE1_BASE f6620000
|
||||||
|
#define CP11X_PCIE2_BASE f6640000
|
||||||
|
|
||||||
|
#include "armada-cp115.dtsi"
|
||||||
|
|
||||||
|
#undef CP11X_NAME
|
||||||
|
#undef CP11X_BASE
|
||||||
|
#undef CP11X_PCIEx_MEM_BASE
|
||||||
|
#undef CP11X_PCIEx_MEM_SIZE
|
||||||
|
#undef CP11X_PCIE0_BASE
|
||||||
|
#undef CP11X_PCIE1_BASE
|
||||||
|
#undef CP11X_PCIE2_BASE
|
||||||
|
|
||||||
|
&cp1_crypto {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_xmdio {
|
||||||
|
status = "okay";
|
||||||
|
cp1_nbaset_phy0: ethernet-phy@3 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <2>;
|
||||||
|
};
|
||||||
|
cp1_nbaset_phy1: ethernet-phy@4 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <0>;
|
||||||
|
};
|
||||||
|
cp1_nbaset_phy2: ethernet-phy@5 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <8>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_ethernet {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
/* CON50 */
|
||||||
|
&cp1_eth0 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "2500base-x";
|
||||||
|
phys = <&cp1_comphy2 0>;
|
||||||
|
phy = <&cp1_nbaset_phy0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_eth1 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "2500base-x";
|
||||||
|
phys = <&cp1_comphy4 1>;
|
||||||
|
phy = <&cp1_nbaset_phy1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_eth2 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "2500base-x";
|
||||||
|
phys = <&cp1_comphy5 2>;
|
||||||
|
phy = <&cp1_nbaset_phy2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_sata0 {
|
||||||
|
status = "okay";
|
||||||
|
sata-port@1 {
|
||||||
|
status = "okay";
|
||||||
|
phys = <&cp1_comphy0 1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_gpio1 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_gpio2 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_i2c0 {
|
||||||
|
status = "okay";
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&cp1_i2c0_pins>;
|
||||||
|
clock-frequency = <100000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_syscon0 {
|
||||||
|
cp1_pinctrl: pinctrl {
|
||||||
|
compatible = "marvell,cp115-standalone-pinctrl";
|
||||||
|
cp1_i2c0_pins: cp1-i2c-pins-0 {
|
||||||
|
marvell,pins = "mpp37", "mpp38";
|
||||||
|
marvell,function = "i2c0";
|
||||||
|
};
|
||||||
|
cp1_spi0_pins: cp1-spi-pins-0 {
|
||||||
|
marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
|
||||||
|
marvell,function = "spi1";
|
||||||
|
};
|
||||||
|
cp1_xhci0_vbus_pins: cp1-xhci0-vbus-pins {
|
||||||
|
marvell,pins = "mpp3";
|
||||||
|
marvell,function = "gpio";
|
||||||
|
};
|
||||||
|
cp1_sfp_pins: sfp-pins {
|
||||||
|
marvell,pins = "mpp8", "mpp9", "mpp10", "mpp11";
|
||||||
|
marvell,function = "gpio";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_usb3_1 {
|
||||||
|
status = "okay";
|
||||||
|
phys = <&cp1_comphy3 1>;
|
||||||
|
phy-names = "usb";
|
||||||
|
};
|
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
chosen {
|
chosen {
|
||||||
stdout-path = "serial0:115200n8";
|
stdout-path = "serial0:115200n8";
|
||||||
|
bootargs-append = " root=/dev/mmcblk0p3";
|
||||||
};
|
};
|
||||||
|
|
||||||
aliases {
|
aliases {
|
||||||
|
@@ -0,0 +1,565 @@
|
|||||||
|
// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Marvell International Ltd.
|
||||||
|
*
|
||||||
|
* Device tree for the CN9132-DB board.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cn9130.dtsi"
|
||||||
|
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
|
#include <dt-bindings/input/input.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
model = "QNAP QHora-322";
|
||||||
|
compatible = "qnap,qhora-322",
|
||||||
|
"marvell,armada-ap807-quad", "marvell,armada-ap807";
|
||||||
|
|
||||||
|
chosen {
|
||||||
|
stdout-path = "serial0:115200n8";
|
||||||
|
bootargs-append = " root=/dev/mmcblk0p3";
|
||||||
|
};
|
||||||
|
|
||||||
|
aliases {
|
||||||
|
i2c0 = &cp1_i2c0;
|
||||||
|
i2c1 = &cp0_i2c0;
|
||||||
|
gpio1 = &cp0_gpio1;
|
||||||
|
gpio2 = &cp0_gpio2;
|
||||||
|
gpio3 = &cp1_gpio1;
|
||||||
|
gpio4 = &cp1_gpio2;
|
||||||
|
gpio5 = &cp2_gpio1;
|
||||||
|
gpio6 = &cp2_gpio2;
|
||||||
|
ethernet0 = &cp0_eth0;
|
||||||
|
ethernet1 = &cp0_eth1;
|
||||||
|
ethernet2 = &cp0_eth2;
|
||||||
|
ethernet3 = &cp1_eth0;
|
||||||
|
ethernet4 = &cp1_eth1;
|
||||||
|
ethernet5 = &cp1_eth2;
|
||||||
|
ethernet6 = &cp2_eth0;
|
||||||
|
ethernet7 = &cp2_eth1;
|
||||||
|
ethernet8 = &cp2_eth2;
|
||||||
|
spi1 = &cp0_spi0;
|
||||||
|
spi2 = &cp0_spi1;
|
||||||
|
led-boot = &led_power;
|
||||||
|
led-failsafe = &led_info;
|
||||||
|
led-running = &led_power;
|
||||||
|
led-upgrade = &led_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
memory@00000000 {
|
||||||
|
device_type = "memory";
|
||||||
|
reg = <0x0 0x0 0x0 0x80000000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
gpio_keys {
|
||||||
|
compatible = "gpio-keys";
|
||||||
|
|
||||||
|
reset {
|
||||||
|
label = "Reset";
|
||||||
|
linux,code = <KEY_RESTART>;
|
||||||
|
gpios = <&cp0_gpio2 4 GPIO_ACTIVE_LOW>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cp2_reg_usb3_vbus0: cp2_usb3_vbus@0 {
|
||||||
|
compatible = "regulator-fixed";
|
||||||
|
regulator-name = "cp2-xhci0-vbus";
|
||||||
|
regulator-min-microvolt = <5000000>;
|
||||||
|
regulator-max-microvolt = <5000000>;
|
||||||
|
enable-active-high;
|
||||||
|
gpio = <&cp2_gpio1 2 GPIO_ACTIVE_HIGH>;
|
||||||
|
};
|
||||||
|
|
||||||
|
cp2_usb3_0_phy0: cp2_usb3_phy0 {
|
||||||
|
compatible = "usb-nop-xceiv";
|
||||||
|
vcc-supply = <&cp2_reg_usb3_vbus0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
cp2_reg_usb3_vbus1: cp2_usb3_vbus@1 {
|
||||||
|
compatible = "regulator-fixed";
|
||||||
|
regulator-name = "cp2-xhci1-vbus";
|
||||||
|
regulator-min-microvolt = <5000000>;
|
||||||
|
regulator-max-microvolt = <5000000>;
|
||||||
|
enable-active-high;
|
||||||
|
gpio = <&cp2_gpio1 3 GPIO_ACTIVE_HIGH>;
|
||||||
|
};
|
||||||
|
|
||||||
|
cp2_usb3_0_phy1: cp2_usb3_phy1 {
|
||||||
|
compatible = "usb-nop-xceiv";
|
||||||
|
vcc-supply = <&cp2_reg_usb3_vbus1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
cp2_sfp_eth0: sfp-eth0 {
|
||||||
|
compatible = "sff,sfp";
|
||||||
|
i2c-bus = <&cp2_sfpp0_i2c>;
|
||||||
|
los-gpio = <&cp2_module_expander1 11 GPIO_ACTIVE_HIGH>;
|
||||||
|
mod-def0-gpio = <&cp2_module_expander1 10 GPIO_ACTIVE_LOW>;
|
||||||
|
tx-disable-gpio = <&cp2_module_expander1 9 GPIO_ACTIVE_HIGH>;
|
||||||
|
tx-fault-gpio = <&cp2_module_expander1 8 GPIO_ACTIVE_HIGH>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&uart0 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_uart0 {
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
puzzle-mcu {
|
||||||
|
compatible = "iei,wt61p803-puzzle";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
current-speed = <115200>;
|
||||||
|
enable-beep;
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
leds {
|
||||||
|
compatible = "iei,wt61p803-puzzle-leds";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
led@0 {
|
||||||
|
reg = <0>;
|
||||||
|
label = "white:network";
|
||||||
|
active-low;
|
||||||
|
};
|
||||||
|
|
||||||
|
led@1 {
|
||||||
|
reg = <1>;
|
||||||
|
label = "green:cloud";
|
||||||
|
active-low;
|
||||||
|
};
|
||||||
|
|
||||||
|
led_info: led@2 {
|
||||||
|
reg = <2>;
|
||||||
|
label = "orange:info";
|
||||||
|
active-low;
|
||||||
|
};
|
||||||
|
|
||||||
|
led_power: led@3 {
|
||||||
|
reg = <3>;
|
||||||
|
label = "yellow:power";
|
||||||
|
active-low;
|
||||||
|
default-state = "on";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
hwmon {
|
||||||
|
compatible = "iei,wt61p803-puzzle-hwmon";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
chassis_fan_group0: fan-group@0 {
|
||||||
|
#cooling-cells = <2>;
|
||||||
|
reg = <0x00>;
|
||||||
|
cooling-levels = <64 102 170 230 250>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&ap_thermal_cpu1 {
|
||||||
|
trips {
|
||||||
|
cpu_active: cpu-active {
|
||||||
|
temperature = <44000>;
|
||||||
|
hysteresis = <2000>;
|
||||||
|
type = "active";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
cooling-maps {
|
||||||
|
fan-map {
|
||||||
|
trip = <&cpu_active>;
|
||||||
|
cooling-device = <&chassis_fan_group0 64 THERMAL_NO_LIMIT>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* on-board eMMC - U9 */
|
||||||
|
&ap_sdhci0 {
|
||||||
|
pinctrl-names = "default";
|
||||||
|
bus-width = <8>;
|
||||||
|
status = "okay";
|
||||||
|
mmc-ddr-1_8v;
|
||||||
|
mmc-hs400-1_8v;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_crypto {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_xmdio {
|
||||||
|
status = "okay";
|
||||||
|
cp0_nbaset_phy0: ethernet-phy@0 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <2>;
|
||||||
|
};
|
||||||
|
cp0_nbaset_phy1: ethernet-phy@1 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <0>;
|
||||||
|
};
|
||||||
|
cp0_nbaset_phy2: ethernet-phy@2 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <8>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_ethernet {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SLM-1521-V2, CON9 */
|
||||||
|
&cp0_eth0 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "10gbase-kr";
|
||||||
|
phys = <&cp0_comphy2 0>;
|
||||||
|
phy = <&cp0_nbaset_phy0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_eth1 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "2500base-x";
|
||||||
|
phys = <&cp0_comphy4 1>;
|
||||||
|
phy = <&cp0_nbaset_phy1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_eth2 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "2500base-x";
|
||||||
|
phys = <&cp0_comphy1 2>;
|
||||||
|
phy = <&cp0_nbaset_phy2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_gpio1 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_gpio2 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_i2c0 {
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&cp0_i2c0_pins>;
|
||||||
|
status = "okay";
|
||||||
|
clock-frequency = <100000>;
|
||||||
|
rtc@32 {
|
||||||
|
compatible = "epson,rx8130";
|
||||||
|
reg = <0x32>;
|
||||||
|
wakeup-source;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_i2c1 {
|
||||||
|
clock-frequency = <100000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SLM-1521-V2, CON6 */
|
||||||
|
&cp0_sata0 {
|
||||||
|
status = "okay";
|
||||||
|
sata-port@1 {
|
||||||
|
status = "okay";
|
||||||
|
phys = <&cp0_comphy0 1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_pcie2 {
|
||||||
|
status = "okay";
|
||||||
|
num-lanes = <1>;
|
||||||
|
num-viewport = <8>;
|
||||||
|
phys = <&cp0_comphy5 2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* U55 */
|
||||||
|
&cp0_spi1 {
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&cp0_spi0_pins>;
|
||||||
|
reg = <0x700680 0x50>, /* control */
|
||||||
|
<0x2000000 0x1000000>; /* CS0 */
|
||||||
|
status = "okay";
|
||||||
|
spi-flash@0 {
|
||||||
|
#address-cells = <0x1>;
|
||||||
|
#size-cells = <0x1>;
|
||||||
|
compatible = "jedec,spi-nor";
|
||||||
|
reg = <0x0>;
|
||||||
|
spi-max-frequency = <40000000>;
|
||||||
|
partitions {
|
||||||
|
compatible = "fixed-partitions";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
partition@0 {
|
||||||
|
label = "U-Boot";
|
||||||
|
reg = <0x0 0x1f0000>;
|
||||||
|
};
|
||||||
|
partition@1f0000 {
|
||||||
|
label = "U-Boot ENV Factory";
|
||||||
|
reg = <0x1f0000 0x10000>;
|
||||||
|
};
|
||||||
|
partition@200000 {
|
||||||
|
label = "Reserved";
|
||||||
|
reg = <0x200000 0x1f0000>;
|
||||||
|
};
|
||||||
|
partition@3f0000 {
|
||||||
|
label = "U-Boot ENV";
|
||||||
|
reg = <0x3f0000 0x10000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_syscon0 {
|
||||||
|
cp0_pinctrl: pinctrl {
|
||||||
|
compatible = "marvell,cp115-standalone-pinctrl";
|
||||||
|
cp0_i2c0_pins: cp0-i2c-pins-0 {
|
||||||
|
marvell,pins = "mpp37", "mpp38";
|
||||||
|
marvell,function = "i2c0";
|
||||||
|
};
|
||||||
|
cp0_i2c1_pins: cp0-i2c-pins-1 {
|
||||||
|
marvell,pins = "mpp35", "mpp36";
|
||||||
|
marvell,function = "i2c1";
|
||||||
|
};
|
||||||
|
cp0_ge1_rgmii_pins: cp0-ge-rgmii-pins-0 {
|
||||||
|
marvell,pins = "mpp0", "mpp1", "mpp2",
|
||||||
|
"mpp3", "mpp4", "mpp5",
|
||||||
|
"mpp6", "mpp7", "mpp8",
|
||||||
|
"mpp9", "mpp10", "mpp11";
|
||||||
|
marvell,function = "ge0";
|
||||||
|
};
|
||||||
|
cp0_ge2_rgmii_pins: cp0-ge-rgmii-pins-1 {
|
||||||
|
marvell,pins = "mpp44", "mpp45", "mpp46",
|
||||||
|
"mpp47", "mpp48", "mpp49",
|
||||||
|
"mpp50", "mpp51", "mpp52",
|
||||||
|
"mpp53", "mpp54", "mpp55";
|
||||||
|
marvell,function = "ge1";
|
||||||
|
};
|
||||||
|
cp0_spi0_pins: cp0-spi-pins-0 {
|
||||||
|
marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
|
||||||
|
marvell,function = "spi1";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp0_usb3_1 {
|
||||||
|
status = "okay";
|
||||||
|
phys = <&cp0_comphy3 1>;
|
||||||
|
phy-names = "usb";
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instantiate the first connected CP115
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CP11X_NAME cp1
|
||||||
|
#define CP11X_BASE f4000000
|
||||||
|
#define CP11X_PCIEx_MEM_BASE(iface) (0xe2000000 + (iface * 0x1000000))
|
||||||
|
#define CP11X_PCIEx_MEM_SIZE(iface) 0xf00000
|
||||||
|
#define CP11X_PCIE0_BASE f4600000
|
||||||
|
#define CP11X_PCIE1_BASE f4620000
|
||||||
|
#define CP11X_PCIE2_BASE f4640000
|
||||||
|
|
||||||
|
#include "armada-cp115.dtsi"
|
||||||
|
|
||||||
|
#undef CP11X_NAME
|
||||||
|
#undef CP11X_BASE
|
||||||
|
#undef CP11X_PCIEx_MEM_BASE
|
||||||
|
#undef CP11X_PCIEx_MEM_SIZE
|
||||||
|
#undef CP11X_PCIE0_BASE
|
||||||
|
#undef CP11X_PCIE1_BASE
|
||||||
|
#undef CP11X_PCIE2_BASE
|
||||||
|
|
||||||
|
&cp1_crypto {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_xmdio {
|
||||||
|
status = "okay";
|
||||||
|
cp1_nbaset_phy0: ethernet-phy@3 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <2>;
|
||||||
|
};
|
||||||
|
cp1_nbaset_phy1: ethernet-phy@4 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <0>;
|
||||||
|
};
|
||||||
|
cp1_nbaset_phy2: ethernet-phy@5 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <8>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_ethernet {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
/* CON50 */
|
||||||
|
&cp1_eth0 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "10gbase-kr";
|
||||||
|
phys = <&cp1_comphy2 0>;
|
||||||
|
phy = <&cp1_nbaset_phy0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_eth1 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "2500base-x";
|
||||||
|
phys = <&cp1_comphy4 1>;
|
||||||
|
phy = <&cp1_nbaset_phy1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_eth2 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "2500base-x";
|
||||||
|
phys = <&cp1_comphy1 2>;
|
||||||
|
phy = <&cp1_nbaset_phy2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_gpio1 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_gpio2 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_i2c0 {
|
||||||
|
status = "okay";
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&cp1_i2c0_pins>;
|
||||||
|
clock-frequency = <100000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp1_syscon0 {
|
||||||
|
cp1_pinctrl: pinctrl {
|
||||||
|
compatible = "marvell,cp115-standalone-pinctrl";
|
||||||
|
cp1_i2c0_pins: cp1-i2c-pins-0 {
|
||||||
|
marvell,pins = "mpp37", "mpp38";
|
||||||
|
marvell,function = "i2c0";
|
||||||
|
};
|
||||||
|
cp1_spi0_pins: cp1-spi-pins-0 {
|
||||||
|
marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16";
|
||||||
|
marvell,function = "spi1";
|
||||||
|
};
|
||||||
|
cp1_xhci0_vbus_pins: cp1-xhci0-vbus-pins {
|
||||||
|
marvell,pins = "mpp3";
|
||||||
|
marvell,function = "gpio";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instantiate the second connected CP115
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CP11X_NAME cp2
|
||||||
|
#define CP11X_BASE f6000000
|
||||||
|
#define CP11X_PCIEx_MEM_BASE(iface) (0xe5000000 + (iface * 0x1000000))
|
||||||
|
#define CP11X_PCIEx_MEM_SIZE(iface) 0xf00000
|
||||||
|
#define CP11X_PCIE0_BASE f6600000
|
||||||
|
#define CP11X_PCIE1_BASE f6620000
|
||||||
|
#define CP11X_PCIE2_BASE f6640000
|
||||||
|
|
||||||
|
#include "armada-cp115.dtsi"
|
||||||
|
|
||||||
|
#undef CP11X_NAME
|
||||||
|
#undef CP11X_BASE
|
||||||
|
#undef CP11X_PCIEx_MEM_BASE
|
||||||
|
#undef CP11X_PCIEx_MEM_SIZE
|
||||||
|
#undef CP11X_PCIE0_BASE
|
||||||
|
#undef CP11X_PCIE1_BASE
|
||||||
|
#undef CP11X_PCIE2_BASE
|
||||||
|
|
||||||
|
&cp2_crypto {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp2_ethernet {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp2_xmdio {
|
||||||
|
status = "okay";
|
||||||
|
cp2_nbaset_phy0: ethernet-phy@6 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <2>;
|
||||||
|
};
|
||||||
|
cp2_nbaset_phy1: ethernet-phy@7 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <0>;
|
||||||
|
};
|
||||||
|
cp2_nbaset_phy2: ethernet-phy@8 {
|
||||||
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
|
reg = <8>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SLM-1521-V2, CON9 */
|
||||||
|
&cp2_eth0 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "10gbase-kr";
|
||||||
|
phys = <&cp2_comphy2 0>;
|
||||||
|
phy = <&cp2_nbaset_phy0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp2_eth1 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "2500base-x";
|
||||||
|
phys = <&cp2_comphy4 1>;
|
||||||
|
phy = <&cp2_nbaset_phy1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp2_eth2 {
|
||||||
|
status = "okay";
|
||||||
|
phy-mode = "2500base-x";
|
||||||
|
phys = <&cp2_comphy1 2>;
|
||||||
|
phy = <&cp2_nbaset_phy2>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp2_gpio1 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp2_gpio2 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp2_i2c0 {
|
||||||
|
clock-frequency = <100000>;
|
||||||
|
/* SLM-1521-V2 - U3 */
|
||||||
|
i2c-mux@72 {
|
||||||
|
compatible = "nxp,pca9544";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
reg = <0x72>;
|
||||||
|
cp2_sfpp0_i2c: i2c@0 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
reg = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c@1 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
reg = <1>;
|
||||||
|
/* U12 */
|
||||||
|
cp2_module_expander1: pca9555@21 {
|
||||||
|
compatible = "nxp,pca9555";
|
||||||
|
pinctrl-names = "default";
|
||||||
|
gpio-controller;
|
||||||
|
#gpio-cells = <2>;
|
||||||
|
reg = <0x21>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&cp2_syscon0 {
|
||||||
|
cp2_pinctrl: pinctrl {
|
||||||
|
compatible = "marvell,cp115-standalone-pinctrl";
|
||||||
|
cp2_i2c0_pins: cp2-i2c-pins-0 {
|
||||||
|
marvell,pins = "mpp37", "mpp38";
|
||||||
|
marvell,function = "i2c0";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
chosen {
|
chosen {
|
||||||
stdout-path = "serial0:115200n8";
|
stdout-path = "serial0:115200n8";
|
||||||
|
bootargs-append = " root=/dev/mmcblk0p3";
|
||||||
};
|
};
|
||||||
|
|
||||||
aliases {
|
aliases {
|
||||||
|
@@ -39,6 +39,16 @@ define Build/boot-img-ext4
|
|||||||
$@.bootimg $@.boot
|
$@.bootimg $@.boot
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
define Build/boot-qnap-img-ext4
|
||||||
|
rm -fR $@.boot
|
||||||
|
mkdir -p $@.boot
|
||||||
|
$(foreach dts,$(DEVICE_DTS), $(CP) $(KDIR)/image-$(dts).dtb $@.boot/$(dts).dtb;)
|
||||||
|
$(CP) $(KDIR)/vmlinux $@.boot/Image
|
||||||
|
make_ext4fs -J -L kernel -l $(CONFIG_TARGET_KERNEL_PARTSIZE)M \
|
||||||
|
$(if $(SOURCE_DATE_EPOCH),-T $(SOURCE_DATE_EPOCH)) \
|
||||||
|
$@.bootimg $@.boot
|
||||||
|
endef
|
||||||
|
|
||||||
define Build/buffalo-kernel-jffs2
|
define Build/buffalo-kernel-jffs2
|
||||||
rm -rf $(KDIR)/kernel_jffs2 $@.fakerd
|
rm -rf $(KDIR)/kernel_jffs2 $@.fakerd
|
||||||
mkdir -p $(KDIR)/kernel_jffs2
|
mkdir -p $(KDIR)/kernel_jffs2
|
||||||
|
@@ -78,3 +78,15 @@ define Device/iei_puzzle-m902
|
|||||||
SOC := cn9132
|
SOC := cn9132
|
||||||
endef
|
endef
|
||||||
TARGET_DEVICES += iei_puzzle-m902
|
TARGET_DEVICES += iei_puzzle-m902
|
||||||
|
|
||||||
|
define Device/qnap_qhora-32x
|
||||||
|
$(call Device/Default-arm64)
|
||||||
|
SOC := cn9132
|
||||||
|
DEVICE_VENDOR := QNAP
|
||||||
|
DEVICE_MODEL := QHora-321/322
|
||||||
|
DEVICE_PACKAGES += kmod-rtc-ds1307
|
||||||
|
DEVICE_DTS := cn9131-db-A cn9131-puzzle-m901 cn9132-db-A cn9132-puzzle-m902
|
||||||
|
SUPPORTED_DEVICES := qnap,qhora-321 qnap,qhora-322 iei,puzzle-m901 iei,puzzle-m902
|
||||||
|
IMAGE/sdcard.img.gz := boot-scr | boot-qnap-img-ext4 | sdcard-img-ext4 | gzip | append-metadata
|
||||||
|
endef
|
||||||
|
TARGET_DEVICES += qnap_qhora-32x
|
||||||
|
@@ -0,0 +1,25 @@
|
|||||||
|
From: David Bauer <mail@david-bauer.net>
|
||||||
|
Date: Thu, 11 Feb 2021 19:57:26 +0100
|
||||||
|
Subject: [PATCH] mtd: spi-nor: add support for Winbond W25Q512
|
||||||
|
|
||||||
|
The Winbond W25Q512 is a 512mb SPI-NOR chip. It supports 4K sectors as
|
||||||
|
well as block protection and Dual-/Quad-read.
|
||||||
|
|
||||||
|
Tested on: Ubiquiti UniFi 6 LR
|
||||||
|
|
||||||
|
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||||
|
|
||||||
|
Ref: https://patchwork.ozlabs.org/project/linux-mtd/patch/20210213151047.11700-1-mail@david-bauer.net/
|
||||||
|
|
||||||
|
--- a/drivers/mtd/spi-nor/spi-nor.c
|
||||||
|
+++ b/drivers/mtd/spi-nor/spi-nor.c
|
||||||
|
@@ -2550,6 +2550,9 @@ static const struct flash_info spi_nor_i
|
||||||
|
.fixups = &w25q256_fixups },
|
||||||
|
{ "w25q256jvm", INFO(0xef7019, 0, 64 * 1024, 512,
|
||||||
|
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
|
||||||
|
+ { "w25q512jv", INFO(0xef4020, 0, 64 * 1024, 1024,
|
||||||
|
+ SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ |
|
||||||
|
+ SPI_NOR_HAS_TB | SPI_NOR_HAS_LOCK) },
|
||||||
|
{ "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024,
|
||||||
|
SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) },
|
||||||
|
|
@@ -51,6 +51,13 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
public readonly bool SupportsIndirectParameters;
|
public readonly bool SupportsIndirectParameters;
|
||||||
public readonly bool SupportsDepthClipControl;
|
public readonly bool SupportsDepthClipControl;
|
||||||
|
|
||||||
|
public readonly int UniformBufferSetIndex;
|
||||||
|
public readonly int StorageBufferSetIndex;
|
||||||
|
public readonly int TextureSetIndex;
|
||||||
|
public readonly int ImageSetIndex;
|
||||||
|
public readonly int ExtraSetBaseIndex;
|
||||||
|
public readonly int MaximumExtraSets;
|
||||||
|
|
||||||
public readonly uint MaximumUniformBuffersPerStage;
|
public readonly uint MaximumUniformBuffersPerStage;
|
||||||
public readonly uint MaximumStorageBuffersPerStage;
|
public readonly uint MaximumStorageBuffersPerStage;
|
||||||
public readonly uint MaximumTexturesPerStage;
|
public readonly uint MaximumTexturesPerStage;
|
||||||
@@ -109,6 +116,12 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
bool supportsViewportSwizzle,
|
bool supportsViewportSwizzle,
|
||||||
bool supportsIndirectParameters,
|
bool supportsIndirectParameters,
|
||||||
bool supportsDepthClipControl,
|
bool supportsDepthClipControl,
|
||||||
|
int uniformBufferSetIndex,
|
||||||
|
int storageBufferSetIndex,
|
||||||
|
int textureSetIndex,
|
||||||
|
int imageSetIndex,
|
||||||
|
int extraSetBaseIndex,
|
||||||
|
int maximumExtraSets,
|
||||||
uint maximumUniformBuffersPerStage,
|
uint maximumUniformBuffersPerStage,
|
||||||
uint maximumStorageBuffersPerStage,
|
uint maximumStorageBuffersPerStage,
|
||||||
uint maximumTexturesPerStage,
|
uint maximumTexturesPerStage,
|
||||||
@@ -164,6 +177,12 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
SupportsViewportSwizzle = supportsViewportSwizzle;
|
SupportsViewportSwizzle = supportsViewportSwizzle;
|
||||||
SupportsIndirectParameters = supportsIndirectParameters;
|
SupportsIndirectParameters = supportsIndirectParameters;
|
||||||
SupportsDepthClipControl = supportsDepthClipControl;
|
SupportsDepthClipControl = supportsDepthClipControl;
|
||||||
|
UniformBufferSetIndex = uniformBufferSetIndex;
|
||||||
|
StorageBufferSetIndex = storageBufferSetIndex;
|
||||||
|
TextureSetIndex = textureSetIndex;
|
||||||
|
ImageSetIndex = imageSetIndex;
|
||||||
|
ExtraSetBaseIndex = extraSetBaseIndex;
|
||||||
|
MaximumExtraSets = maximumExtraSets;
|
||||||
MaximumUniformBuffersPerStage = maximumUniformBuffersPerStage;
|
MaximumUniformBuffersPerStage = maximumUniformBuffersPerStage;
|
||||||
MaximumStorageBuffersPerStage = maximumStorageBuffersPerStage;
|
MaximumStorageBuffersPerStage = maximumStorageBuffersPerStage;
|
||||||
MaximumTexturesPerStage = maximumTexturesPerStage;
|
MaximumTexturesPerStage = maximumTexturesPerStage;
|
||||||
|
@@ -60,6 +60,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
|
|
||||||
void SetImage(ShaderStage stage, int binding, ITexture texture, Format imageFormat);
|
void SetImage(ShaderStage stage, int binding, ITexture texture, Format imageFormat);
|
||||||
void SetImageArray(ShaderStage stage, int binding, IImageArray array);
|
void SetImageArray(ShaderStage stage, int binding, IImageArray array);
|
||||||
|
void SetImageArraySeparate(ShaderStage stage, int setIndex, IImageArray array);
|
||||||
|
|
||||||
void SetLineParameters(float width, bool smooth);
|
void SetLineParameters(float width, bool smooth);
|
||||||
|
|
||||||
@@ -91,6 +92,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
|
|
||||||
void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler);
|
void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler);
|
||||||
void SetTextureArray(ShaderStage stage, int binding, ITextureArray array);
|
void SetTextureArray(ShaderStage stage, int binding, ITextureArray array);
|
||||||
|
void SetTextureArraySeparate(ShaderStage stage, int setIndex, ITextureArray array);
|
||||||
|
|
||||||
void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers);
|
void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers);
|
||||||
void SetUniformBuffers(ReadOnlySpan<BufferAssignment> buffers);
|
void SetUniformBuffers(ReadOnlySpan<BufferAssignment> buffers);
|
||||||
|
@@ -124,6 +124,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||||||
Register<SetUniformBuffersCommand>(CommandType.SetUniformBuffers);
|
Register<SetUniformBuffersCommand>(CommandType.SetUniformBuffers);
|
||||||
Register<SetImageCommand>(CommandType.SetImage);
|
Register<SetImageCommand>(CommandType.SetImage);
|
||||||
Register<SetImageArrayCommand>(CommandType.SetImageArray);
|
Register<SetImageArrayCommand>(CommandType.SetImageArray);
|
||||||
|
Register<SetImageArraySeparateCommand>(CommandType.SetImageArraySeparate);
|
||||||
Register<SetIndexBufferCommand>(CommandType.SetIndexBuffer);
|
Register<SetIndexBufferCommand>(CommandType.SetIndexBuffer);
|
||||||
Register<SetLineParametersCommand>(CommandType.SetLineParameters);
|
Register<SetLineParametersCommand>(CommandType.SetLineParameters);
|
||||||
Register<SetLogicOpStateCommand>(CommandType.SetLogicOpState);
|
Register<SetLogicOpStateCommand>(CommandType.SetLogicOpState);
|
||||||
@@ -141,6 +142,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||||||
Register<SetStencilTestCommand>(CommandType.SetStencilTest);
|
Register<SetStencilTestCommand>(CommandType.SetStencilTest);
|
||||||
Register<SetTextureAndSamplerCommand>(CommandType.SetTextureAndSampler);
|
Register<SetTextureAndSamplerCommand>(CommandType.SetTextureAndSampler);
|
||||||
Register<SetTextureArrayCommand>(CommandType.SetTextureArray);
|
Register<SetTextureArrayCommand>(CommandType.SetTextureArray);
|
||||||
|
Register<SetTextureArraySeparateCommand>(CommandType.SetTextureArraySeparate);
|
||||||
Register<SetUserClipDistanceCommand>(CommandType.SetUserClipDistance);
|
Register<SetUserClipDistanceCommand>(CommandType.SetUserClipDistance);
|
||||||
Register<SetVertexAttribsCommand>(CommandType.SetVertexAttribs);
|
Register<SetVertexAttribsCommand>(CommandType.SetVertexAttribs);
|
||||||
Register<SetVertexBuffersCommand>(CommandType.SetVertexBuffers);
|
Register<SetVertexBuffersCommand>(CommandType.SetVertexBuffers);
|
||||||
|
@@ -84,6 +84,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||||||
SetUniformBuffers,
|
SetUniformBuffers,
|
||||||
SetImage,
|
SetImage,
|
||||||
SetImageArray,
|
SetImageArray,
|
||||||
|
SetImageArraySeparate,
|
||||||
SetIndexBuffer,
|
SetIndexBuffer,
|
||||||
SetLineParameters,
|
SetLineParameters,
|
||||||
SetLogicOpState,
|
SetLogicOpState,
|
||||||
@@ -101,6 +102,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||||||
SetStencilTest,
|
SetStencilTest,
|
||||||
SetTextureAndSampler,
|
SetTextureAndSampler,
|
||||||
SetTextureArray,
|
SetTextureArray,
|
||||||
|
SetTextureArraySeparate,
|
||||||
SetUserClipDistance,
|
SetUserClipDistance,
|
||||||
SetVertexAttribs,
|
SetVertexAttribs,
|
||||||
SetVertexBuffers,
|
SetVertexBuffers,
|
||||||
|
@@ -0,0 +1,26 @@
|
|||||||
|
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||||
|
using Ryujinx.Graphics.GAL.Multithreading.Resources;
|
||||||
|
using Ryujinx.Graphics.Shader;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||||
|
{
|
||||||
|
struct SetImageArraySeparateCommand : IGALCommand, IGALCommand<SetImageArraySeparateCommand>
|
||||||
|
{
|
||||||
|
public readonly CommandType CommandType => CommandType.SetImageArraySeparate;
|
||||||
|
private ShaderStage _stage;
|
||||||
|
private int _setIndex;
|
||||||
|
private TableRef<IImageArray> _array;
|
||||||
|
|
||||||
|
public void Set(ShaderStage stage, int setIndex, TableRef<IImageArray> array)
|
||||||
|
{
|
||||||
|
_stage = stage;
|
||||||
|
_setIndex = setIndex;
|
||||||
|
_array = array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Run(ref SetImageArraySeparateCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||||
|
{
|
||||||
|
renderer.Pipeline.SetImageArraySeparate(command._stage, command._setIndex, command._array.GetAs<ThreadedImageArray>(threaded)?.Base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,26 @@
|
|||||||
|
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||||
|
using Ryujinx.Graphics.GAL.Multithreading.Resources;
|
||||||
|
using Ryujinx.Graphics.Shader;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||||
|
{
|
||||||
|
struct SetTextureArraySeparateCommand : IGALCommand, IGALCommand<SetTextureArraySeparateCommand>
|
||||||
|
{
|
||||||
|
public readonly CommandType CommandType => CommandType.SetTextureArraySeparate;
|
||||||
|
private ShaderStage _stage;
|
||||||
|
private int _setIndex;
|
||||||
|
private TableRef<ITextureArray> _array;
|
||||||
|
|
||||||
|
public void Set(ShaderStage stage, int setIndex, TableRef<ITextureArray> array)
|
||||||
|
{
|
||||||
|
_stage = stage;
|
||||||
|
_setIndex = setIndex;
|
||||||
|
_array = array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Run(ref SetTextureArraySeparateCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||||
|
{
|
||||||
|
renderer.Pipeline.SetTextureArraySeparate(command._stage, command._setIndex, command._array.GetAs<ThreadedTextureArray>(threaded)?.Base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -189,6 +189,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||||||
_renderer.QueueCommand();
|
_renderer.QueueCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetImageArraySeparate(ShaderStage stage, int setIndex, IImageArray array)
|
||||||
|
{
|
||||||
|
_renderer.New<SetImageArraySeparateCommand>().Set(stage, setIndex, Ref(array));
|
||||||
|
_renderer.QueueCommand();
|
||||||
|
}
|
||||||
|
|
||||||
public void SetIndexBuffer(BufferRange buffer, IndexType type)
|
public void SetIndexBuffer(BufferRange buffer, IndexType type)
|
||||||
{
|
{
|
||||||
_renderer.New<SetIndexBufferCommand>().Set(buffer, type);
|
_renderer.New<SetIndexBufferCommand>().Set(buffer, type);
|
||||||
@@ -297,6 +303,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||||||
_renderer.QueueCommand();
|
_renderer.QueueCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetTextureArraySeparate(ShaderStage stage, int setIndex, ITextureArray array)
|
||||||
|
{
|
||||||
|
_renderer.New<SetTextureArraySeparateCommand>().Set(stage, setIndex, Ref(array));
|
||||||
|
_renderer.QueueCommand();
|
||||||
|
}
|
||||||
|
|
||||||
public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
|
public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
|
||||||
{
|
{
|
||||||
_renderer.New<SetTransformFeedbackBuffersCommand>().Set(_renderer.CopySpan(buffers));
|
_renderer.New<SetTransformFeedbackBuffersCommand>().Set(_renderer.CopySpan(buffers));
|
||||||
|
@@ -19,6 +19,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Format Format { get; }
|
public Format Format { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shader texture host set index.
|
||||||
|
/// </summary>
|
||||||
|
public int Set { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shader texture host binding point.
|
/// Shader texture host binding point.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -54,15 +59,17 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="target">The shader sampler target type</param>
|
/// <param name="target">The shader sampler target type</param>
|
||||||
/// <param name="format">Format of the image as declared on the shader</param>
|
/// <param name="format">Format of the image as declared on the shader</param>
|
||||||
|
/// <param name="set">Shader texture host set index</param>
|
||||||
/// <param name="binding">The shader texture binding point</param>
|
/// <param name="binding">The shader texture binding point</param>
|
||||||
/// <param name="arrayLength">For array of textures, this indicates the length of the array. A value of one indicates it is not an array</param>
|
/// <param name="arrayLength">For array of textures, this indicates the length of the array. A value of one indicates it is not an array</param>
|
||||||
/// <param name="cbufSlot">Constant buffer slot where the texture handle is located</param>
|
/// <param name="cbufSlot">Constant buffer slot where the texture handle is located</param>
|
||||||
/// <param name="handle">The shader texture handle (read index into the texture constant buffer)</param>
|
/// <param name="handle">The shader texture handle (read index into the texture constant buffer)</param>
|
||||||
/// <param name="flags">The texture's usage flags, indicating how it is used in the shader</param>
|
/// <param name="flags">The texture's usage flags, indicating how it is used in the shader</param>
|
||||||
public TextureBindingInfo(Target target, Format format, int binding, int arrayLength, int cbufSlot, int handle, TextureUsageFlags flags)
|
public TextureBindingInfo(Target target, Format format, int set, int binding, int arrayLength, int cbufSlot, int handle, TextureUsageFlags flags)
|
||||||
{
|
{
|
||||||
Target = target;
|
Target = target;
|
||||||
Format = format;
|
Format = format;
|
||||||
|
Set = set;
|
||||||
Binding = binding;
|
Binding = binding;
|
||||||
ArrayLength = arrayLength;
|
ArrayLength = arrayLength;
|
||||||
CbufSlot = cbufSlot;
|
CbufSlot = cbufSlot;
|
||||||
@@ -74,6 +81,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// Constructs the texture binding information structure.
|
/// Constructs the texture binding information structure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="target">The shader sampler target type</param>
|
/// <param name="target">The shader sampler target type</param>
|
||||||
|
/// <param name="set">Shader texture host set index</param>
|
||||||
/// <param name="binding">The shader texture binding point</param>
|
/// <param name="binding">The shader texture binding point</param>
|
||||||
/// <param name="arrayLength">For array of textures, this indicates the length of the array. A value of one indicates it is not an array</param>
|
/// <param name="arrayLength">For array of textures, this indicates the length of the array. A value of one indicates it is not an array</param>
|
||||||
/// <param name="cbufSlot">Constant buffer slot where the texture handle is located</param>
|
/// <param name="cbufSlot">Constant buffer slot where the texture handle is located</param>
|
||||||
@@ -82,12 +90,13 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// <param name="isSamplerOnly">Indicates that the binding is for a sampler</param>
|
/// <param name="isSamplerOnly">Indicates that the binding is for a sampler</param>
|
||||||
public TextureBindingInfo(
|
public TextureBindingInfo(
|
||||||
Target target,
|
Target target,
|
||||||
|
int set,
|
||||||
int binding,
|
int binding,
|
||||||
int arrayLength,
|
int arrayLength,
|
||||||
int cbufSlot,
|
int cbufSlot,
|
||||||
int handle,
|
int handle,
|
||||||
TextureUsageFlags flags,
|
TextureUsageFlags flags,
|
||||||
bool isSamplerOnly) : this(target, 0, binding, arrayLength, cbufSlot, handle, flags)
|
bool isSamplerOnly) : this(target, 0, set, binding, arrayLength, cbufSlot, handle, flags)
|
||||||
{
|
{
|
||||||
IsSamplerOnly = isSamplerOnly;
|
IsSamplerOnly = isSamplerOnly;
|
||||||
}
|
}
|
||||||
|
@@ -566,7 +566,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
int stageIndex,
|
int stageIndex,
|
||||||
int textureBufferIndex,
|
int textureBufferIndex,
|
||||||
SamplerIndex samplerIndex,
|
SamplerIndex samplerIndex,
|
||||||
TextureBindingInfo bindingInfo)
|
in TextureBindingInfo bindingInfo)
|
||||||
{
|
{
|
||||||
Update(texturePool, samplerPool, stage, stageIndex, textureBufferIndex, isImage: false, samplerIndex, bindingInfo);
|
Update(texturePool, samplerPool, stage, stageIndex, textureBufferIndex, isImage: false, samplerIndex, bindingInfo);
|
||||||
}
|
}
|
||||||
@@ -579,7 +579,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// <param name="stageIndex">Shader stage index where the array is used</param>
|
/// <param name="stageIndex">Shader stage index where the array is used</param>
|
||||||
/// <param name="textureBufferIndex">Texture constant buffer index</param>
|
/// <param name="textureBufferIndex">Texture constant buffer index</param>
|
||||||
/// <param name="bindingInfo">Array binding information</param>
|
/// <param name="bindingInfo">Array binding information</param>
|
||||||
public void UpdateImageArray(TexturePool texturePool, ShaderStage stage, int stageIndex, int textureBufferIndex, TextureBindingInfo bindingInfo)
|
public void UpdateImageArray(TexturePool texturePool, ShaderStage stage, int stageIndex, int textureBufferIndex, in TextureBindingInfo bindingInfo)
|
||||||
{
|
{
|
||||||
Update(texturePool, null, stage, stageIndex, textureBufferIndex, isImage: true, SamplerIndex.ViaHeaderIndex, bindingInfo);
|
Update(texturePool, null, stage, stageIndex, textureBufferIndex, isImage: true, SamplerIndex.ViaHeaderIndex, bindingInfo);
|
||||||
}
|
}
|
||||||
@@ -603,7 +603,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
int textureBufferIndex,
|
int textureBufferIndex,
|
||||||
bool isImage,
|
bool isImage,
|
||||||
SamplerIndex samplerIndex,
|
SamplerIndex samplerIndex,
|
||||||
TextureBindingInfo bindingInfo)
|
in TextureBindingInfo bindingInfo)
|
||||||
{
|
{
|
||||||
if (IsDirectHandleType(bindingInfo.Handle))
|
if (IsDirectHandleType(bindingInfo.Handle))
|
||||||
{
|
{
|
||||||
@@ -623,7 +623,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// <param name="stage">Shader stage where the array is used</param>
|
/// <param name="stage">Shader stage where the array is used</param>
|
||||||
/// <param name="isImage">Whether the array is a image or texture array</param>
|
/// <param name="isImage">Whether the array is a image or texture array</param>
|
||||||
/// <param name="bindingInfo">Array binding information</param>
|
/// <param name="bindingInfo">Array binding information</param>
|
||||||
private void UpdateFromPool(TexturePool texturePool, SamplerPool samplerPool, ShaderStage stage, bool isImage, TextureBindingInfo bindingInfo)
|
private void UpdateFromPool(TexturePool texturePool, SamplerPool samplerPool, ShaderStage stage, bool isImage, in TextureBindingInfo bindingInfo)
|
||||||
{
|
{
|
||||||
CacheEntry entry = GetOrAddEntry(texturePool, samplerPool, bindingInfo, isImage, out bool isNewEntry);
|
CacheEntry entry = GetOrAddEntry(texturePool, samplerPool, bindingInfo, isImage, out bool isNewEntry);
|
||||||
|
|
||||||
@@ -638,11 +638,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
if (isImage)
|
if (isImage)
|
||||||
{
|
{
|
||||||
_context.Renderer.Pipeline.SetImageArray(stage, bindingInfo.Binding, entry.ImageArray);
|
SetImageArray(stage, bindingInfo, entry.ImageArray);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_context.Renderer.Pipeline.SetTextureArray(stage, bindingInfo.Binding, entry.TextureArray);
|
SetTextureArray(stage, bindingInfo, entry.TextureArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -737,14 +737,14 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
entry.ImageArray.SetFormats(0, formats);
|
entry.ImageArray.SetFormats(0, formats);
|
||||||
entry.ImageArray.SetImages(0, textures);
|
entry.ImageArray.SetImages(0, textures);
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetImageArray(stage, bindingInfo.Binding, entry.ImageArray);
|
SetImageArray(stage, bindingInfo, entry.ImageArray);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
entry.TextureArray.SetSamplers(0, samplers);
|
entry.TextureArray.SetSamplers(0, samplers);
|
||||||
entry.TextureArray.SetTextures(0, textures);
|
entry.TextureArray.SetTextures(0, textures);
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetTextureArray(stage, bindingInfo.Binding, entry.TextureArray);
|
SetTextureArray(stage, bindingInfo, entry.TextureArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -767,7 +767,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
int textureBufferIndex,
|
int textureBufferIndex,
|
||||||
bool isImage,
|
bool isImage,
|
||||||
SamplerIndex samplerIndex,
|
SamplerIndex samplerIndex,
|
||||||
TextureBindingInfo bindingInfo)
|
in TextureBindingInfo bindingInfo)
|
||||||
{
|
{
|
||||||
(textureBufferIndex, int samplerBufferIndex) = TextureHandle.UnpackSlots(bindingInfo.CbufSlot, textureBufferIndex);
|
(textureBufferIndex, int samplerBufferIndex) = TextureHandle.UnpackSlots(bindingInfo.CbufSlot, textureBufferIndex);
|
||||||
|
|
||||||
@@ -800,11 +800,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
if (isImage)
|
if (isImage)
|
||||||
{
|
{
|
||||||
_context.Renderer.Pipeline.SetImageArray(stage, bindingInfo.Binding, entry.ImageArray);
|
SetImageArray(stage, bindingInfo, entry.ImageArray);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_context.Renderer.Pipeline.SetTextureArray(stage, bindingInfo.Binding, entry.TextureArray);
|
SetTextureArray(stage, bindingInfo, entry.TextureArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -829,11 +829,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
if (isImage)
|
if (isImage)
|
||||||
{
|
{
|
||||||
_context.Renderer.Pipeline.SetImageArray(stage, bindingInfo.Binding, entry.ImageArray);
|
SetImageArray(stage, bindingInfo, entry.ImageArray);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_context.Renderer.Pipeline.SetTextureArray(stage, bindingInfo.Binding, entry.TextureArray);
|
SetTextureArray(stage, bindingInfo, entry.TextureArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -950,14 +950,50 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
entry.ImageArray.SetFormats(0, formats);
|
entry.ImageArray.SetFormats(0, formats);
|
||||||
entry.ImageArray.SetImages(0, textures);
|
entry.ImageArray.SetImages(0, textures);
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetImageArray(stage, bindingInfo.Binding, entry.ImageArray);
|
SetImageArray(stage, bindingInfo, entry.ImageArray);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
entry.TextureArray.SetSamplers(0, samplers);
|
entry.TextureArray.SetSamplers(0, samplers);
|
||||||
entry.TextureArray.SetTextures(0, textures);
|
entry.TextureArray.SetTextures(0, textures);
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetTextureArray(stage, bindingInfo.Binding, entry.TextureArray);
|
SetTextureArray(stage, bindingInfo, entry.TextureArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates a texture array binding on the host.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stage">Shader stage where the array is used</param>
|
||||||
|
/// <param name="bindingInfo">Array binding information</param>
|
||||||
|
/// <param name="array">Texture array</param>
|
||||||
|
private void SetTextureArray(ShaderStage stage, in TextureBindingInfo bindingInfo, ITextureArray array)
|
||||||
|
{
|
||||||
|
if (bindingInfo.Set >= _context.Capabilities.ExtraSetBaseIndex && _context.Capabilities.MaximumExtraSets != 0)
|
||||||
|
{
|
||||||
|
_context.Renderer.Pipeline.SetTextureArraySeparate(stage, bindingInfo.Set, array);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_context.Renderer.Pipeline.SetTextureArray(stage, bindingInfo.Binding, array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates a image array binding on the host.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stage">Shader stage where the array is used</param>
|
||||||
|
/// <param name="bindingInfo">Array binding information</param>
|
||||||
|
/// <param name="array">Image array</param>
|
||||||
|
private void SetImageArray(ShaderStage stage, in TextureBindingInfo bindingInfo, IImageArray array)
|
||||||
|
{
|
||||||
|
if (bindingInfo.Set >= _context.Capabilities.ExtraSetBaseIndex && _context.Capabilities.MaximumExtraSets != 0)
|
||||||
|
{
|
||||||
|
_context.Renderer.Pipeline.SetImageArraySeparate(stage, bindingInfo.Set, array);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_context.Renderer.Pipeline.SetImageArray(stage, bindingInfo.Binding, array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -973,7 +1009,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
private CacheEntry GetOrAddEntry(
|
private CacheEntry GetOrAddEntry(
|
||||||
TexturePool texturePool,
|
TexturePool texturePool,
|
||||||
SamplerPool samplerPool,
|
SamplerPool samplerPool,
|
||||||
TextureBindingInfo bindingInfo,
|
in TextureBindingInfo bindingInfo,
|
||||||
bool isImage,
|
bool isImage,
|
||||||
out bool isNew)
|
out bool isNew)
|
||||||
{
|
{
|
||||||
@@ -1015,7 +1051,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
private CacheEntryFromBuffer GetOrAddEntry(
|
private CacheEntryFromBuffer GetOrAddEntry(
|
||||||
TexturePool texturePool,
|
TexturePool texturePool,
|
||||||
SamplerPool samplerPool,
|
SamplerPool samplerPool,
|
||||||
TextureBindingInfo bindingInfo,
|
in TextureBindingInfo bindingInfo,
|
||||||
bool isImage,
|
bool isImage,
|
||||||
ref BufferBounds textureBufferBounds,
|
ref BufferBounds textureBufferBounds,
|
||||||
out bool isNew)
|
out bool isNew)
|
||||||
|
@@ -62,6 +62,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
|
|
||||||
var result = new TextureBindingInfo(
|
var result = new TextureBindingInfo(
|
||||||
target,
|
target,
|
||||||
|
descriptor.Set,
|
||||||
descriptor.Binding,
|
descriptor.Binding,
|
||||||
descriptor.ArrayLength,
|
descriptor.ArrayLength,
|
||||||
descriptor.CbufSlot,
|
descriptor.CbufSlot,
|
||||||
@@ -90,6 +91,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
var result = new TextureBindingInfo(
|
var result = new TextureBindingInfo(
|
||||||
target,
|
target,
|
||||||
format,
|
format,
|
||||||
|
descriptor.Set,
|
||||||
descriptor.Binding,
|
descriptor.Binding,
|
||||||
descriptor.ArrayLength,
|
descriptor.ArrayLength,
|
||||||
descriptor.CbufSlot,
|
descriptor.CbufSlot,
|
||||||
|
@@ -125,9 +125,18 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
CompressionAlgorithm algorithm = CompressionAlgorithm.None;
|
CompressionAlgorithm algorithm = CompressionAlgorithm.None;
|
||||||
Read(ref algorithm);
|
Read(ref algorithm);
|
||||||
|
|
||||||
if (algorithm == CompressionAlgorithm.Deflate)
|
switch (algorithm)
|
||||||
{
|
{
|
||||||
_activeStream = new DeflateStream(_stream, CompressionMode.Decompress, true);
|
case CompressionAlgorithm.None:
|
||||||
|
break;
|
||||||
|
case CompressionAlgorithm.Deflate:
|
||||||
|
_activeStream = new DeflateStream(_stream, CompressionMode.Decompress, true);
|
||||||
|
break;
|
||||||
|
case CompressionAlgorithm.Brotli:
|
||||||
|
_activeStream = new BrotliStream(_stream, CompressionMode.Decompress, true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentException($"Invalid compression algorithm \"{algorithm}\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,9 +148,18 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
{
|
{
|
||||||
Write(ref algorithm);
|
Write(ref algorithm);
|
||||||
|
|
||||||
if (algorithm == CompressionAlgorithm.Deflate)
|
switch (algorithm)
|
||||||
{
|
{
|
||||||
_activeStream = new DeflateStream(_stream, CompressionLevel.Fastest, true);
|
case CompressionAlgorithm.None:
|
||||||
|
break;
|
||||||
|
case CompressionAlgorithm.Deflate:
|
||||||
|
_activeStream = new DeflateStream(_stream, CompressionLevel.Fastest, true);
|
||||||
|
break;
|
||||||
|
case CompressionAlgorithm.Brotli:
|
||||||
|
_activeStream = new BrotliStream(_stream, CompressionLevel.Fastest, true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentException($"Invalid compression algorithm \"{algorithm}\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +205,14 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
}
|
}
|
||||||
stream.Dispose();
|
stream.Dispose();
|
||||||
break;
|
break;
|
||||||
|
case CompressionAlgorithm.Brotli:
|
||||||
|
stream = new BrotliStream(stream, CompressionMode.Decompress, true);
|
||||||
|
for (int offset = 0; offset < data.Length;)
|
||||||
|
{
|
||||||
|
offset += stream.Read(data[offset..]);
|
||||||
|
}
|
||||||
|
stream.Dispose();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,6 +236,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
stream.Write(data);
|
stream.Write(data);
|
||||||
stream.Dispose();
|
stream.Dispose();
|
||||||
break;
|
break;
|
||||||
|
case CompressionAlgorithm.Brotli:
|
||||||
|
stream = new BrotliStream(stream, CompressionLevel.Fastest, true);
|
||||||
|
stream.Write(data);
|
||||||
|
stream.Dispose();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,5 +14,10 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
/// Deflate compression (RFC 1951).
|
/// Deflate compression (RFC 1951).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Deflate,
|
Deflate,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Brotli compression (RFC 7932).
|
||||||
|
/// </summary>
|
||||||
|
Brotli,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
/// <returns>Compression algorithm</returns>
|
/// <returns>Compression algorithm</returns>
|
||||||
public static CompressionAlgorithm GetCompressionAlgorithm()
|
public static CompressionAlgorithm GetCompressionAlgorithm()
|
||||||
{
|
{
|
||||||
return CompressionAlgorithm.Deflate;
|
return CompressionAlgorithm.Brotli;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
private const ushort FileFormatVersionMajor = 1;
|
private const ushort FileFormatVersionMajor = 1;
|
||||||
private const ushort FileFormatVersionMinor = 2;
|
private const ushort FileFormatVersionMinor = 2;
|
||||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||||
private const uint CodeGenVersion = 5936;
|
private const uint CodeGenVersion = 6852;
|
||||||
|
|
||||||
private const string SharedTocFileName = "shared.toc";
|
private const string SharedTocFileName = "shared.toc";
|
||||||
private const string SharedDataFileName = "shared.data";
|
private const string SharedDataFileName = "shared.data";
|
||||||
|
@@ -51,7 +51,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
_reservedImages = rrc.ReservedImages;
|
_reservedImages = rrc.ReservedImages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CreateConstantBufferBinding(int index)
|
public SetBindingPair CreateConstantBufferBinding(int index)
|
||||||
{
|
{
|
||||||
int binding;
|
int binding;
|
||||||
|
|
||||||
@@ -64,10 +64,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
binding = _resourceCounts.UniformBuffersCount++;
|
binding = _resourceCounts.UniformBuffersCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return binding + _reservedConstantBuffers;
|
return new SetBindingPair(_context.Capabilities.UniformBufferSetIndex, binding + _reservedConstantBuffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CreateImageBinding(int count, bool isBuffer)
|
public SetBindingPair CreateImageBinding(int count, bool isBuffer)
|
||||||
{
|
{
|
||||||
int binding;
|
int binding;
|
||||||
|
|
||||||
@@ -96,10 +96,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
_resourceCounts.ImagesCount += count;
|
_resourceCounts.ImagesCount += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return binding + _reservedImages;
|
return new SetBindingPair(_context.Capabilities.ImageSetIndex, binding + _reservedImages);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CreateStorageBufferBinding(int index)
|
public SetBindingPair CreateStorageBufferBinding(int index)
|
||||||
{
|
{
|
||||||
int binding;
|
int binding;
|
||||||
|
|
||||||
@@ -112,10 +112,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
binding = _resourceCounts.StorageBuffersCount++;
|
binding = _resourceCounts.StorageBuffersCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return binding + _reservedStorageBuffers;
|
return new SetBindingPair(_context.Capabilities.StorageBufferSetIndex, binding + _reservedStorageBuffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CreateTextureBinding(int count, bool isBuffer)
|
public SetBindingPair CreateTextureBinding(int count, bool isBuffer)
|
||||||
{
|
{
|
||||||
int binding;
|
int binding;
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
_resourceCounts.TexturesCount += count;
|
_resourceCounts.TexturesCount += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return binding + _reservedTextures;
|
return new SetBindingPair(_context.Capabilities.TextureSetIndex, binding + _reservedTextures);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetBindingFromIndex(int index, uint maxPerStage, string resourceName)
|
private int GetBindingFromIndex(int index, uint maxPerStage, string resourceName)
|
||||||
@@ -183,6 +183,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
return maxPerStage * Constants.ShaderStages;
|
return maxPerStage * Constants.ShaderStages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int CreateExtraSet()
|
||||||
|
{
|
||||||
|
if (_resourceCounts.SetsCount >= _context.Capabilities.MaximumExtraSets)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _context.Capabilities.ExtraSetBaseIndex + _resourceCounts.SetsCount++;
|
||||||
|
}
|
||||||
|
|
||||||
public int QueryHostGatherBiasPrecision() => _context.Capabilities.GatherBiasPrecision;
|
public int QueryHostGatherBiasPrecision() => _context.Capabilities.GatherBiasPrecision;
|
||||||
|
|
||||||
public bool QueryHostReducedPrecision() => _context.Capabilities.ReduceShaderPrecision;
|
public bool QueryHostReducedPrecision() => _context.Capabilities.ReduceShaderPrecision;
|
||||||
|
@@ -24,5 +24,10 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// Total of images used by the shaders.
|
/// Total of images used by the shaders.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int ImagesCount;
|
public int ImagesCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Total of extra sets used by the shaders.
|
||||||
|
/// </summary>
|
||||||
|
public int SetsCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Shader
|
namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
@@ -9,13 +10,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class ShaderInfoBuilder
|
class ShaderInfoBuilder
|
||||||
{
|
{
|
||||||
private const int TotalSets = 4;
|
|
||||||
|
|
||||||
private const int UniformSetIndex = 0;
|
|
||||||
private const int StorageSetIndex = 1;
|
|
||||||
private const int TextureSetIndex = 2;
|
|
||||||
private const int ImageSetIndex = 3;
|
|
||||||
|
|
||||||
private const ResourceStages SupportBufferStages =
|
private const ResourceStages SupportBufferStages =
|
||||||
ResourceStages.Compute |
|
ResourceStages.Compute |
|
||||||
ResourceStages.Vertex |
|
ResourceStages.Vertex |
|
||||||
@@ -36,8 +30,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
private readonly int _reservedTextures;
|
private readonly int _reservedTextures;
|
||||||
private readonly int _reservedImages;
|
private readonly int _reservedImages;
|
||||||
|
|
||||||
private readonly List<ResourceDescriptor>[] _resourceDescriptors;
|
private List<ResourceDescriptor>[] _resourceDescriptors;
|
||||||
private readonly List<ResourceUsage>[] _resourceUsages;
|
private List<ResourceUsage>[] _resourceUsages;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new shader info builder.
|
/// Creates a new shader info builder.
|
||||||
@@ -51,17 +45,27 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
|
|
||||||
_fragmentOutputMap = -1;
|
_fragmentOutputMap = -1;
|
||||||
|
|
||||||
_resourceDescriptors = new List<ResourceDescriptor>[TotalSets];
|
int uniformSetIndex = context.Capabilities.UniformBufferSetIndex;
|
||||||
_resourceUsages = new List<ResourceUsage>[TotalSets];
|
int storageSetIndex = context.Capabilities.StorageBufferSetIndex;
|
||||||
|
int textureSetIndex = context.Capabilities.TextureSetIndex;
|
||||||
|
int imageSetIndex = context.Capabilities.ImageSetIndex;
|
||||||
|
|
||||||
for (int index = 0; index < TotalSets; index++)
|
int totalSets = Math.Max(uniformSetIndex, storageSetIndex);
|
||||||
|
totalSets = Math.Max(totalSets, textureSetIndex);
|
||||||
|
totalSets = Math.Max(totalSets, imageSetIndex);
|
||||||
|
totalSets++;
|
||||||
|
|
||||||
|
_resourceDescriptors = new List<ResourceDescriptor>[totalSets];
|
||||||
|
_resourceUsages = new List<ResourceUsage>[totalSets];
|
||||||
|
|
||||||
|
for (int index = 0; index < totalSets; index++)
|
||||||
{
|
{
|
||||||
_resourceDescriptors[index] = new();
|
_resourceDescriptors[index] = new();
|
||||||
_resourceUsages[index] = new();
|
_resourceUsages[index] = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
AddDescriptor(SupportBufferStages, ResourceType.UniformBuffer, UniformSetIndex, 0, 1);
|
AddDescriptor(SupportBufferStages, ResourceType.UniformBuffer, uniformSetIndex, 0, 1);
|
||||||
AddUsage(SupportBufferStages, ResourceType.UniformBuffer, UniformSetIndex, 0, 1);
|
AddUsage(SupportBufferStages, ResourceType.UniformBuffer, uniformSetIndex, 0, 1);
|
||||||
|
|
||||||
ResourceReservationCounts rrc = new(!context.Capabilities.SupportsTransformFeedback && tfEnabled, vertexAsCompute);
|
ResourceReservationCounts rrc = new(!context.Capabilities.SupportsTransformFeedback && tfEnabled, vertexAsCompute);
|
||||||
|
|
||||||
@@ -73,12 +77,20 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
// TODO: Handle that better? Maybe we should only set the binding that are really needed on each shader.
|
// TODO: Handle that better? Maybe we should only set the binding that are really needed on each shader.
|
||||||
ResourceStages stages = vertexAsCompute ? ResourceStages.Compute | ResourceStages.Vertex : VtgStages;
|
ResourceStages stages = vertexAsCompute ? ResourceStages.Compute | ResourceStages.Vertex : VtgStages;
|
||||||
|
|
||||||
PopulateDescriptorAndUsages(stages, ResourceType.UniformBuffer, UniformSetIndex, 1, rrc.ReservedConstantBuffers - 1);
|
PopulateDescriptorAndUsages(stages, ResourceType.UniformBuffer, uniformSetIndex, 1, rrc.ReservedConstantBuffers - 1);
|
||||||
PopulateDescriptorAndUsages(stages, ResourceType.StorageBuffer, StorageSetIndex, 0, rrc.ReservedStorageBuffers);
|
PopulateDescriptorAndUsages(stages, ResourceType.StorageBuffer, storageSetIndex, 0, rrc.ReservedStorageBuffers);
|
||||||
PopulateDescriptorAndUsages(stages, ResourceType.BufferTexture, TextureSetIndex, 0, rrc.ReservedTextures);
|
PopulateDescriptorAndUsages(stages, ResourceType.BufferTexture, textureSetIndex, 0, rrc.ReservedTextures);
|
||||||
PopulateDescriptorAndUsages(stages, ResourceType.BufferImage, ImageSetIndex, 0, rrc.ReservedImages);
|
PopulateDescriptorAndUsages(stages, ResourceType.BufferImage, imageSetIndex, 0, rrc.ReservedImages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Populates descriptors and usages for vertex as compute and transform feedback emulation reserved resources.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stages">Shader stages where the resources are used</param>
|
||||||
|
/// <param name="type">Resource type</param>
|
||||||
|
/// <param name="setIndex">Resource set index where the resources are used</param>
|
||||||
|
/// <param name="start">First binding number</param>
|
||||||
|
/// <param name="count">Amount of bindings</param>
|
||||||
private void PopulateDescriptorAndUsages(ResourceStages stages, ResourceType type, int setIndex, int start, int count)
|
private void PopulateDescriptorAndUsages(ResourceStages stages, ResourceType type, int setIndex, int start, int count)
|
||||||
{
|
{
|
||||||
AddDescriptor(stages, type, setIndex, start, count);
|
AddDescriptor(stages, type, setIndex, start, count);
|
||||||
@@ -127,18 +139,23 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
int textureBinding = _reservedTextures + stageIndex * texturesPerStage * 2;
|
int textureBinding = _reservedTextures + stageIndex * texturesPerStage * 2;
|
||||||
int imageBinding = _reservedImages + stageIndex * imagesPerStage * 2;
|
int imageBinding = _reservedImages + stageIndex * imagesPerStage * 2;
|
||||||
|
|
||||||
AddDescriptor(stages, ResourceType.UniformBuffer, UniformSetIndex, uniformBinding, uniformsPerStage);
|
int uniformSetIndex = _context.Capabilities.UniformBufferSetIndex;
|
||||||
AddDescriptor(stages, ResourceType.StorageBuffer, StorageSetIndex, storageBinding, storagesPerStage);
|
int storageSetIndex = _context.Capabilities.StorageBufferSetIndex;
|
||||||
AddDualDescriptor(stages, ResourceType.TextureAndSampler, ResourceType.BufferTexture, TextureSetIndex, textureBinding, texturesPerStage);
|
int textureSetIndex = _context.Capabilities.TextureSetIndex;
|
||||||
AddDualDescriptor(stages, ResourceType.Image, ResourceType.BufferImage, ImageSetIndex, imageBinding, imagesPerStage);
|
int imageSetIndex = _context.Capabilities.ImageSetIndex;
|
||||||
|
|
||||||
AddArrayDescriptors(info.Textures, stages, TextureSetIndex, isImage: false);
|
AddDescriptor(stages, ResourceType.UniformBuffer, uniformSetIndex, uniformBinding, uniformsPerStage);
|
||||||
AddArrayDescriptors(info.Images, stages, TextureSetIndex, isImage: true);
|
AddDescriptor(stages, ResourceType.StorageBuffer, storageSetIndex, storageBinding, storagesPerStage);
|
||||||
|
AddDualDescriptor(stages, ResourceType.TextureAndSampler, ResourceType.BufferTexture, textureSetIndex, textureBinding, texturesPerStage);
|
||||||
|
AddDualDescriptor(stages, ResourceType.Image, ResourceType.BufferImage, imageSetIndex, imageBinding, imagesPerStage);
|
||||||
|
|
||||||
AddUsage(info.CBuffers, stages, UniformSetIndex, isStorage: false);
|
AddArrayDescriptors(info.Textures, stages, isImage: false);
|
||||||
AddUsage(info.SBuffers, stages, StorageSetIndex, isStorage: true);
|
AddArrayDescriptors(info.Images, stages, isImage: true);
|
||||||
AddUsage(info.Textures, stages, TextureSetIndex, isImage: false);
|
|
||||||
AddUsage(info.Images, stages, ImageSetIndex, isImage: true);
|
AddUsage(info.CBuffers, stages, isStorage: false);
|
||||||
|
AddUsage(info.SBuffers, stages, isStorage: true);
|
||||||
|
AddUsage(info.Textures, stages, isImage: false);
|
||||||
|
AddUsage(info.Images, stages, isImage: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -177,9 +194,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="textures">Textures to be added</param>
|
/// <param name="textures">Textures to be added</param>
|
||||||
/// <param name="stages">Stages where the textures are used</param>
|
/// <param name="stages">Stages where the textures are used</param>
|
||||||
/// <param name="setIndex">Descriptor set index where the textures will be bound</param>
|
|
||||||
/// <param name="isImage">True for images, false for textures</param>
|
/// <param name="isImage">True for images, false for textures</param>
|
||||||
private void AddArrayDescriptors(IEnumerable<TextureDescriptor> textures, ResourceStages stages, int setIndex, bool isImage)
|
private void AddArrayDescriptors(IEnumerable<TextureDescriptor> textures, ResourceStages stages, bool isImage)
|
||||||
{
|
{
|
||||||
foreach (TextureDescriptor texture in textures)
|
foreach (TextureDescriptor texture in textures)
|
||||||
{
|
{
|
||||||
@@ -187,7 +203,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
{
|
{
|
||||||
ResourceType type = GetTextureResourceType(texture, isImage);
|
ResourceType type = GetTextureResourceType(texture, isImage);
|
||||||
|
|
||||||
_resourceDescriptors[setIndex].Add(new ResourceDescriptor(texture.Binding, texture.ArrayLength, type, stages));
|
GetDescriptors(texture.Set).Add(new ResourceDescriptor(texture.Binding, texture.ArrayLength, type, stages));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,13 +229,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="buffers">Buffers to be added</param>
|
/// <param name="buffers">Buffers to be added</param>
|
||||||
/// <param name="stages">Stages where the buffers are used</param>
|
/// <param name="stages">Stages where the buffers are used</param>
|
||||||
/// <param name="setIndex">Descriptor set index where the buffers will be bound</param>
|
|
||||||
/// <param name="isStorage">True for storage buffers, false for uniform buffers</param>
|
/// <param name="isStorage">True for storage buffers, false for uniform buffers</param>
|
||||||
private void AddUsage(IEnumerable<BufferDescriptor> buffers, ResourceStages stages, int setIndex, bool isStorage)
|
private void AddUsage(IEnumerable<BufferDescriptor> buffers, ResourceStages stages, bool isStorage)
|
||||||
{
|
{
|
||||||
foreach (BufferDescriptor buffer in buffers)
|
foreach (BufferDescriptor buffer in buffers)
|
||||||
{
|
{
|
||||||
_resourceUsages[setIndex].Add(new ResourceUsage(
|
GetUsages(buffer.Set).Add(new ResourceUsage(
|
||||||
buffer.Binding,
|
buffer.Binding,
|
||||||
1,
|
1,
|
||||||
isStorage ? ResourceType.StorageBuffer : ResourceType.UniformBuffer,
|
isStorage ? ResourceType.StorageBuffer : ResourceType.UniformBuffer,
|
||||||
@@ -232,18 +247,65 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="textures">Textures to be added</param>
|
/// <param name="textures">Textures to be added</param>
|
||||||
/// <param name="stages">Stages where the textures are used</param>
|
/// <param name="stages">Stages where the textures are used</param>
|
||||||
/// <param name="setIndex">Descriptor set index where the textures will be bound</param>
|
|
||||||
/// <param name="isImage">True for images, false for textures</param>
|
/// <param name="isImage">True for images, false for textures</param>
|
||||||
private void AddUsage(IEnumerable<TextureDescriptor> textures, ResourceStages stages, int setIndex, bool isImage)
|
private void AddUsage(IEnumerable<TextureDescriptor> textures, ResourceStages stages, bool isImage)
|
||||||
{
|
{
|
||||||
foreach (TextureDescriptor texture in textures)
|
foreach (TextureDescriptor texture in textures)
|
||||||
{
|
{
|
||||||
ResourceType type = GetTextureResourceType(texture, isImage);
|
ResourceType type = GetTextureResourceType(texture, isImage);
|
||||||
|
|
||||||
_resourceUsages[setIndex].Add(new ResourceUsage(texture.Binding, texture.ArrayLength, type, stages));
|
GetUsages(texture.Set).Add(new ResourceUsage(texture.Binding, texture.ArrayLength, type, stages));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of resource descriptors for a given set index. A new list will be created if needed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="setIndex">Resource set index</param>
|
||||||
|
/// <returns>List of resource descriptors</returns>
|
||||||
|
private List<ResourceDescriptor> GetDescriptors(int setIndex)
|
||||||
|
{
|
||||||
|
if (_resourceDescriptors.Length <= setIndex)
|
||||||
|
{
|
||||||
|
int oldLength = _resourceDescriptors.Length;
|
||||||
|
Array.Resize(ref _resourceDescriptors, setIndex + 1);
|
||||||
|
|
||||||
|
for (int index = oldLength; index <= setIndex; index++)
|
||||||
|
{
|
||||||
|
_resourceDescriptors[index] = new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _resourceDescriptors[setIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of resource usages for a given set index. A new list will be created if needed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="setIndex">Resource set index</param>
|
||||||
|
/// <returns>List of resource usages</returns>
|
||||||
|
private List<ResourceUsage> GetUsages(int setIndex)
|
||||||
|
{
|
||||||
|
if (_resourceUsages.Length <= setIndex)
|
||||||
|
{
|
||||||
|
int oldLength = _resourceUsages.Length;
|
||||||
|
Array.Resize(ref _resourceUsages, setIndex + 1);
|
||||||
|
|
||||||
|
for (int index = oldLength; index <= setIndex; index++)
|
||||||
|
{
|
||||||
|
_resourceUsages[index] = new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _resourceUsages[setIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a resource type from a texture descriptor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="texture">Texture descriptor</param>
|
||||||
|
/// <param name="isImage">Whether the texture is a image texture (writable) or not (sampled)</param>
|
||||||
|
/// <returns>Resource type</returns>
|
||||||
private static ResourceType GetTextureResourceType(TextureDescriptor texture, bool isImage)
|
private static ResourceType GetTextureResourceType(TextureDescriptor texture, bool isImage)
|
||||||
{
|
{
|
||||||
bool isBuffer = (texture.Type & SamplerType.Mask) == SamplerType.TextureBuffer;
|
bool isBuffer = (texture.Type & SamplerType.Mask) == SamplerType.TextureBuffer;
|
||||||
@@ -278,10 +340,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
/// <returns>Shader information</returns>
|
/// <returns>Shader information</returns>
|
||||||
public ShaderInfo Build(ProgramPipelineState? pipeline, bool fromCache = false)
|
public ShaderInfo Build(ProgramPipelineState? pipeline, bool fromCache = false)
|
||||||
{
|
{
|
||||||
var descriptors = new ResourceDescriptorCollection[TotalSets];
|
int totalSets = _resourceDescriptors.Length;
|
||||||
var usages = new ResourceUsageCollection[TotalSets];
|
|
||||||
|
|
||||||
for (int index = 0; index < TotalSets; index++)
|
var descriptors = new ResourceDescriptorCollection[totalSets];
|
||||||
|
var usages = new ResourceUsageCollection[totalSets];
|
||||||
|
|
||||||
|
for (int index = 0; index < totalSets; index++)
|
||||||
{
|
{
|
||||||
descriptors[index] = new ResourceDescriptorCollection(_resourceDescriptors[index].ToArray().AsReadOnly());
|
descriptors[index] = new ResourceDescriptorCollection(_resourceDescriptors[index].ToArray().AsReadOnly());
|
||||||
usages[index] = new ResourceUsageCollection(_resourceUsages[index].ToArray().AsReadOnly());
|
usages[index] = new ResourceUsageCollection(_resourceUsages[index].ToArray().AsReadOnly());
|
||||||
|
@@ -187,6 +187,12 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle,
|
supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle,
|
||||||
supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters,
|
supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters,
|
||||||
supportsDepthClipControl: true,
|
supportsDepthClipControl: true,
|
||||||
|
uniformBufferSetIndex: 0,
|
||||||
|
storageBufferSetIndex: 1,
|
||||||
|
textureSetIndex: 2,
|
||||||
|
imageSetIndex: 3,
|
||||||
|
extraSetBaseIndex: 0,
|
||||||
|
maximumExtraSets: 0,
|
||||||
maximumUniformBuffersPerStage: 13, // TODO: Avoid hardcoding those limits here and get from driver?
|
maximumUniformBuffersPerStage: 13, // TODO: Avoid hardcoding those limits here and get from driver?
|
||||||
maximumStorageBuffersPerStage: 16,
|
maximumStorageBuffersPerStage: 16,
|
||||||
maximumTexturesPerStage: 32,
|
maximumTexturesPerStage: 32,
|
||||||
|
@@ -963,6 +963,11 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
(array as ImageArray).Bind(binding);
|
(array as ImageArray).Bind(binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetImageArraySeparate(ShaderStage stage, int setIndex, IImageArray array)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("OpenGL does not support descriptor sets.");
|
||||||
|
}
|
||||||
|
|
||||||
public void SetIndexBuffer(BufferRange buffer, IndexType type)
|
public void SetIndexBuffer(BufferRange buffer, IndexType type)
|
||||||
{
|
{
|
||||||
_elementsType = type.Convert();
|
_elementsType = type.Convert();
|
||||||
@@ -1312,6 +1317,11 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
(array as TextureArray).Bind(binding);
|
(array as TextureArray).Bind(binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetTextureArraySeparate(ShaderStage stage, int setIndex, ITextureArray array)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("OpenGL does not support descriptor sets.");
|
||||||
|
}
|
||||||
|
|
||||||
public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
|
public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
|
||||||
{
|
{
|
||||||
if (_tfEnabled)
|
if (_tfEnabled)
|
||||||
|
@@ -4,14 +4,16 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
{
|
{
|
||||||
// New fields should be added to the end of the struct to keep disk shader cache compatibility.
|
// New fields should be added to the end of the struct to keep disk shader cache compatibility.
|
||||||
|
|
||||||
|
public readonly int Set;
|
||||||
public readonly int Binding;
|
public readonly int Binding;
|
||||||
public readonly byte Slot;
|
public readonly byte Slot;
|
||||||
public readonly byte SbCbSlot;
|
public readonly byte SbCbSlot;
|
||||||
public readonly ushort SbCbOffset;
|
public readonly ushort SbCbOffset;
|
||||||
public readonly BufferUsageFlags Flags;
|
public readonly BufferUsageFlags Flags;
|
||||||
|
|
||||||
public BufferDescriptor(int binding, int slot)
|
public BufferDescriptor(int set, int binding, int slot)
|
||||||
{
|
{
|
||||||
|
Set = set;
|
||||||
Binding = binding;
|
Binding = binding;
|
||||||
Slot = (byte)slot;
|
Slot = (byte)slot;
|
||||||
SbCbSlot = 0;
|
SbCbSlot = 0;
|
||||||
@@ -19,8 +21,9 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
Flags = BufferUsageFlags.None;
|
Flags = BufferUsageFlags.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferDescriptor(int binding, int slot, int sbCbSlot, int sbCbOffset, BufferUsageFlags flags)
|
public BufferDescriptor(int set, int binding, int slot, int sbCbSlot, int sbCbOffset, BufferUsageFlags flags)
|
||||||
{
|
{
|
||||||
|
Set = set;
|
||||||
Binding = binding;
|
Binding = binding;
|
||||||
Slot = (byte)slot;
|
Slot = (byte)slot;
|
||||||
SbCbSlot = (byte)sbCbSlot;
|
SbCbSlot = (byte)sbCbSlot;
|
||||||
|
@@ -462,7 +462,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.Properties.Textures.TryGetValue(texOp.Binding, out TextureDefinition definition);
|
context.Properties.Textures.TryGetValue(texOp.GetTextureSetAndBinding(), out TextureDefinition definition);
|
||||||
bool hasLod = !definition.Type.HasFlag(SamplerType.Multisample) && (definition.Type & SamplerType.Mask) != SamplerType.TextureBuffer;
|
bool hasLod = !definition.Type.HasFlag(SamplerType.Multisample) && (definition.Type & SamplerType.Mask) != SamplerType.TextureBuffer;
|
||||||
string texCall;
|
string texCall;
|
||||||
|
|
||||||
@@ -639,7 +639,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
|
|
||||||
private static string GetSamplerName(CodeGenContext context, AstTextureOperation texOp, ref int srcIndex)
|
private static string GetSamplerName(CodeGenContext context, AstTextureOperation texOp, ref int srcIndex)
|
||||||
{
|
{
|
||||||
TextureDefinition textureDefinition = context.Properties.Textures[texOp.Binding];
|
TextureDefinition textureDefinition = context.Properties.Textures[texOp.GetTextureSetAndBinding()];
|
||||||
string name = textureDefinition.Name;
|
string name = textureDefinition.Name;
|
||||||
|
|
||||||
if (textureDefinition.ArrayLength != 1)
|
if (textureDefinition.ArrayLength != 1)
|
||||||
@@ -649,7 +649,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
|
|
||||||
if (texOp.IsSeparate)
|
if (texOp.IsSeparate)
|
||||||
{
|
{
|
||||||
TextureDefinition samplerDefinition = context.Properties.Textures[texOp.SamplerBinding];
|
TextureDefinition samplerDefinition = context.Properties.Textures[texOp.GetSamplerSetAndBinding()];
|
||||||
string samplerName = samplerDefinition.Name;
|
string samplerName = samplerDefinition.Name;
|
||||||
|
|
||||||
if (samplerDefinition.ArrayLength != 1)
|
if (samplerDefinition.ArrayLength != 1)
|
||||||
@@ -665,7 +665,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
|
|
||||||
private static string GetImageName(CodeGenContext context, AstTextureOperation texOp, ref int srcIndex)
|
private static string GetImageName(CodeGenContext context, AstTextureOperation texOp, ref int srcIndex)
|
||||||
{
|
{
|
||||||
TextureDefinition definition = context.Properties.Images[texOp.Binding];
|
TextureDefinition definition = context.Properties.Images[texOp.GetTextureSetAndBinding()];
|
||||||
string name = definition.Name;
|
string name = definition.Name;
|
||||||
|
|
||||||
if (definition.ArrayLength != 1)
|
if (definition.ArrayLength != 1)
|
||||||
|
@@ -33,9 +33,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
public Dictionary<int, Instruction> LocalMemories { get; } = new();
|
public Dictionary<int, Instruction> LocalMemories { get; } = new();
|
||||||
public Dictionary<int, Instruction> SharedMemories { get; } = new();
|
public Dictionary<int, Instruction> SharedMemories { get; } = new();
|
||||||
|
|
||||||
public Dictionary<int, SamplerType> SamplersTypes { get; } = new();
|
public Dictionary<SetBindingPair, SamplerType> SamplersTypes { get; } = new();
|
||||||
public Dictionary<int, SamplerDeclaration> Samplers { get; } = new();
|
public Dictionary<SetBindingPair, SamplerDeclaration> Samplers { get; } = new();
|
||||||
public Dictionary<int, ImageDeclaration> Images { get; } = new();
|
public Dictionary<SetBindingPair, ImageDeclaration> Images { get; } = new();
|
||||||
|
|
||||||
public Dictionary<IoDefinition, Instruction> Inputs { get; } = new();
|
public Dictionary<IoDefinition, Instruction> Inputs { get; } = new();
|
||||||
public Dictionary<IoDefinition, Instruction> Outputs { get; } = new();
|
public Dictionary<IoDefinition, Instruction> Outputs { get; } = new();
|
||||||
|
@@ -208,13 +208,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
var sampledImageVariable = context.Variable(sampledImageArrayPointerType, StorageClass.UniformConstant);
|
var sampledImageVariable = context.Variable(sampledImageArrayPointerType, StorageClass.UniformConstant);
|
||||||
|
|
||||||
context.Samplers.Add(sampler.Binding, new SamplerDeclaration(
|
context.Samplers.Add(new(sampler.Set, sampler.Binding), new SamplerDeclaration(
|
||||||
imageType,
|
imageType,
|
||||||
sampledImageType,
|
sampledImageType,
|
||||||
sampledImagePointerType,
|
sampledImagePointerType,
|
||||||
sampledImageVariable,
|
sampledImageVariable,
|
||||||
sampler.ArrayLength != 1));
|
sampler.ArrayLength != 1));
|
||||||
context.SamplersTypes.Add(sampler.Binding, sampler.Type);
|
context.SamplersTypes.Add(new(sampler.Set, sampler.Binding), sampler.Type);
|
||||||
|
|
||||||
context.Name(sampledImageVariable, sampler.Name);
|
context.Name(sampledImageVariable, sampler.Name);
|
||||||
context.Decorate(sampledImageVariable, Decoration.DescriptorSet, (LiteralInteger)setIndex);
|
context.Decorate(sampledImageVariable, Decoration.DescriptorSet, (LiteralInteger)setIndex);
|
||||||
@@ -256,7 +256,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
var imageVariable = context.Variable(imageArrayPointerType, StorageClass.UniformConstant);
|
var imageVariable = context.Variable(imageArrayPointerType, StorageClass.UniformConstant);
|
||||||
|
|
||||||
context.Images.Add(image.Binding, new ImageDeclaration(imageType, imagePointerType, imageVariable, image.ArrayLength != 1));
|
context.Images.Add(new(image.Set, image.Binding), new ImageDeclaration(imageType, imagePointerType, imageVariable, image.ArrayLength != 1));
|
||||||
|
|
||||||
context.Name(imageVariable, image.Name);
|
context.Name(imageVariable, image.Name);
|
||||||
context.Decorate(imageVariable, Decoration.DescriptorSet, (LiteralInteger)setIndex);
|
context.Decorate(imageVariable, Decoration.DescriptorSet, (LiteralInteger)setIndex);
|
||||||
|
@@ -602,7 +602,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageDeclaration declaration = context.Images[texOp.Binding];
|
ImageDeclaration declaration = context.Images[texOp.GetTextureSetAndBinding()];
|
||||||
SpvInstruction image = declaration.Image;
|
SpvInstruction image = declaration.Image;
|
||||||
|
|
||||||
SpvInstruction resultType = context.GetType(componentType);
|
SpvInstruction resultType = context.GetType(componentType);
|
||||||
@@ -681,7 +681,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageDeclaration declaration = context.Images[texOp.Binding];
|
ImageDeclaration declaration = context.Images[texOp.GetTextureSetAndBinding()];
|
||||||
SpvInstruction image = declaration.Image;
|
SpvInstruction image = declaration.Image;
|
||||||
|
|
||||||
if (declaration.IsIndexed)
|
if (declaration.IsIndexed)
|
||||||
@@ -738,7 +738,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageDeclaration declaration = context.Images[texOp.Binding];
|
ImageDeclaration declaration = context.Images[texOp.GetTextureSetAndBinding()];
|
||||||
SpvInstruction image = declaration.Image;
|
SpvInstruction image = declaration.Image;
|
||||||
|
|
||||||
if (declaration.IsIndexed)
|
if (declaration.IsIndexed)
|
||||||
@@ -837,7 +837,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||||
}
|
}
|
||||||
|
|
||||||
SamplerDeclaration declaration = context.Samplers[texOp.Binding];
|
SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()];
|
||||||
SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex);
|
SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex);
|
||||||
|
|
||||||
int pCount = texOp.Type.GetDimensions();
|
int pCount = texOp.Type.GetDimensions();
|
||||||
@@ -1161,7 +1161,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||||
}
|
}
|
||||||
|
|
||||||
SamplerDeclaration declaration = context.Samplers[texOp.Binding];
|
SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()];
|
||||||
SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex);
|
SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex);
|
||||||
|
|
||||||
int coordsCount = texOp.Type.GetDimensions();
|
int coordsCount = texOp.Type.GetDimensions();
|
||||||
@@ -1433,7 +1433,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
int srcIndex = 0;
|
int srcIndex = 0;
|
||||||
|
|
||||||
SamplerDeclaration declaration = context.Samplers[texOp.Binding];
|
SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()];
|
||||||
SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex);
|
SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex);
|
||||||
|
|
||||||
image = context.Image(declaration.ImageType, image);
|
image = context.Image(declaration.ImageType, image);
|
||||||
@@ -1449,7 +1449,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
|
|
||||||
int srcIndex = 0;
|
int srcIndex = 0;
|
||||||
|
|
||||||
SamplerDeclaration declaration = context.Samplers[texOp.Binding];
|
SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()];
|
||||||
SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex);
|
SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex);
|
||||||
|
|
||||||
image = context.Image(declaration.ImageType, image);
|
image = context.Image(declaration.ImageType, image);
|
||||||
@@ -1460,7 +1460,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var type = context.SamplersTypes[texOp.Binding];
|
var type = context.SamplersTypes[texOp.GetTextureSetAndBinding()];
|
||||||
bool hasLod = !type.HasFlag(SamplerType.Multisample) && type != SamplerType.TextureBuffer;
|
bool hasLod = !type.HasFlag(SamplerType.Multisample) && type != SamplerType.TextureBuffer;
|
||||||
|
|
||||||
int dimensions = (type & SamplerType.Mask) == SamplerType.TextureCube ? 2 : type.GetDimensions();
|
int dimensions = (type & SamplerType.Mask) == SamplerType.TextureCube ? 2 : type.GetDimensions();
|
||||||
@@ -1889,7 +1889,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
{
|
{
|
||||||
image = context.Load(declaration.ImageType, image);
|
image = context.Load(declaration.ImageType, image);
|
||||||
|
|
||||||
SamplerDeclaration samplerDeclaration = context.Samplers[texOp.SamplerBinding];
|
SamplerDeclaration samplerDeclaration = context.Samplers[texOp.GetSamplerSetAndBinding()];
|
||||||
|
|
||||||
SpvInstruction sampler = samplerDeclaration.Image;
|
SpvInstruction sampler = samplerDeclaration.Image;
|
||||||
|
|
||||||
|
@@ -27,34 +27,43 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize);
|
ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries the binding number of a constant buffer.
|
/// Gets the binding number of a constant buffer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">Constant buffer index</param>
|
/// <param name="index">Constant buffer index</param>
|
||||||
/// <returns>Binding number</returns>
|
/// <returns>Binding number</returns>
|
||||||
int CreateConstantBufferBinding(int index);
|
SetBindingPair CreateConstantBufferBinding(int index);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries the binding number of an image.
|
/// Gets the binding number of an image.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="count">For array of images, the number of elements of the array, otherwise it should be 1</param>
|
/// <param name="count">For array of images, the number of elements of the array, otherwise it should be 1</param>
|
||||||
/// <param name="isBuffer">Indicates if the image is a buffer image</param>
|
/// <param name="isBuffer">Indicates if the image is a buffer image</param>
|
||||||
/// <returns>Binding number</returns>
|
/// <returns>Binding number</returns>
|
||||||
int CreateImageBinding(int count, bool isBuffer);
|
SetBindingPair CreateImageBinding(int count, bool isBuffer);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries the binding number of a storage buffer.
|
/// Gets the binding number of a storage buffer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">Storage buffer index</param>
|
/// <param name="index">Storage buffer index</param>
|
||||||
/// <returns>Binding number</returns>
|
/// <returns>Binding number</returns>
|
||||||
int CreateStorageBufferBinding(int index);
|
SetBindingPair CreateStorageBufferBinding(int index);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries the binding number of a texture.
|
/// Gets the binding number of a texture.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="count">For array of textures, the number of elements of the array, otherwise it should be 1</param>
|
/// <param name="count">For array of textures, the number of elements of the array, otherwise it should be 1</param>
|
||||||
/// <param name="isBuffer">Indicates if the texture is a buffer texture</param>
|
/// <param name="isBuffer">Indicates if the texture is a buffer texture</param>
|
||||||
/// <returns>Binding number</returns>
|
/// <returns>Binding number</returns>
|
||||||
int CreateTextureBinding(int count, bool isBuffer);
|
SetBindingPair CreateTextureBinding(int count, bool isBuffer);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the set index for an additional set, or -1 if there's no extra set available.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Extra set index, or -1 if not available</returns>
|
||||||
|
int CreateExtraSet()
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries Local Size X for compute shaders.
|
/// Queries Local Size X for compute shaders.
|
||||||
|
@@ -278,7 +278,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
flags |= TextureFlags.Bindless;
|
flags |= TextureFlags.Bindless;
|
||||||
}
|
}
|
||||||
|
|
||||||
int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
SetBindingPair setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding(
|
||||||
Instruction.ImageAtomic,
|
Instruction.ImageAtomic,
|
||||||
type,
|
type,
|
||||||
format,
|
format,
|
||||||
@@ -286,7 +286,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
TextureOperation.DefaultCbufSlot,
|
TextureOperation.DefaultCbufSlot,
|
||||||
imm);
|
imm);
|
||||||
|
|
||||||
Operand res = context.ImageAtomic(type, format, flags, binding, sources);
|
Operand res = context.ImageAtomic(type, format, flags, setAndBinding, sources);
|
||||||
|
|
||||||
context.Copy(d, res);
|
context.Copy(d, res);
|
||||||
}
|
}
|
||||||
@@ -389,7 +389,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
|
|
||||||
TextureFormat format = isBindless ? TextureFormat.Unknown : ShaderProperties.GetTextureFormat(context.TranslatorContext.GpuAccessor, handle);
|
TextureFormat format = isBindless ? TextureFormat.Unknown : ShaderProperties.GetTextureFormat(context.TranslatorContext.GpuAccessor, handle);
|
||||||
|
|
||||||
int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
SetBindingPair setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding(
|
||||||
Instruction.ImageLoad,
|
Instruction.ImageLoad,
|
||||||
type,
|
type,
|
||||||
format,
|
format,
|
||||||
@@ -397,7 +397,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
TextureOperation.DefaultCbufSlot,
|
TextureOperation.DefaultCbufSlot,
|
||||||
handle);
|
handle);
|
||||||
|
|
||||||
context.ImageLoad(type, format, flags, binding, (int)componentMask, dests, sources);
|
context.ImageLoad(type, format, flags, setAndBinding, (int)componentMask, dests, sources);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -432,7 +432,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
|
|
||||||
TextureFormat format = GetTextureFormat(size);
|
TextureFormat format = GetTextureFormat(size);
|
||||||
|
|
||||||
int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
SetBindingPair setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding(
|
||||||
Instruction.ImageLoad,
|
Instruction.ImageLoad,
|
||||||
type,
|
type,
|
||||||
format,
|
format,
|
||||||
@@ -440,7 +440,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
TextureOperation.DefaultCbufSlot,
|
TextureOperation.DefaultCbufSlot,
|
||||||
handle);
|
handle);
|
||||||
|
|
||||||
context.ImageLoad(type, format, flags, binding, compMask, dests, sources);
|
context.ImageLoad(type, format, flags, setAndBinding, compMask, dests, sources);
|
||||||
|
|
||||||
switch (size)
|
switch (size)
|
||||||
{
|
{
|
||||||
@@ -552,7 +552,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
flags |= TextureFlags.Bindless;
|
flags |= TextureFlags.Bindless;
|
||||||
}
|
}
|
||||||
|
|
||||||
int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
SetBindingPair setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding(
|
||||||
Instruction.ImageAtomic,
|
Instruction.ImageAtomic,
|
||||||
type,
|
type,
|
||||||
format,
|
format,
|
||||||
@@ -560,7 +560,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
TextureOperation.DefaultCbufSlot,
|
TextureOperation.DefaultCbufSlot,
|
||||||
imm);
|
imm);
|
||||||
|
|
||||||
context.ImageAtomic(type, format, flags, binding, sources);
|
context.ImageAtomic(type, format, flags, setAndBinding, sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitSust(
|
private static void EmitSust(
|
||||||
@@ -679,7 +679,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
flags |= TextureFlags.Coherent;
|
flags |= TextureFlags.Coherent;
|
||||||
}
|
}
|
||||||
|
|
||||||
int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
SetBindingPair setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding(
|
||||||
Instruction.ImageStore,
|
Instruction.ImageStore,
|
||||||
type,
|
type,
|
||||||
format,
|
format,
|
||||||
@@ -687,7 +687,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
TextureOperation.DefaultCbufSlot,
|
TextureOperation.DefaultCbufSlot,
|
||||||
handle);
|
handle);
|
||||||
|
|
||||||
context.ImageStore(type, format, flags, binding, sources);
|
context.ImageStore(type, format, flags, setAndBinding, sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetComponentSizeInBytesLog2(SuatomSize size)
|
private static int GetComponentSizeInBytesLog2(SuatomSize size)
|
||||||
|
@@ -885,7 +885,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
return Register(dest++, RegisterType.Gpr);
|
return Register(dest++, RegisterType.Gpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
SetBindingPair setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding(
|
||||||
Instruction.Lod,
|
Instruction.Lod,
|
||||||
type,
|
type,
|
||||||
TextureFormat.Unknown,
|
TextureFormat.Unknown,
|
||||||
@@ -913,7 +913,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The instruction component order is the inverse of GLSL's.
|
// The instruction component order is the inverse of GLSL's.
|
||||||
Operand res = context.Lod(type, flags, binding, compIndex ^ 1, sources);
|
Operand res = context.Lod(type, flags, setAndBinding, compIndex ^ 1, sources);
|
||||||
|
|
||||||
res = context.FPMultiply(res, ConstF(256.0f));
|
res = context.FPMultiply(res, ConstF(256.0f));
|
||||||
|
|
||||||
@@ -1116,12 +1116,12 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
|
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
|
||||||
int binding;
|
SetBindingPair setAndBinding;
|
||||||
|
|
||||||
switch (query)
|
switch (query)
|
||||||
{
|
{
|
||||||
case TexQuery.TexHeaderDimension:
|
case TexQuery.TexHeaderDimension:
|
||||||
binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding(
|
||||||
Instruction.TextureQuerySize,
|
Instruction.TextureQuerySize,
|
||||||
type,
|
type,
|
||||||
TextureFormat.Unknown,
|
TextureFormat.Unknown,
|
||||||
@@ -1140,13 +1140,13 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.Copy(d, context.TextureQuerySize(type, flags, binding, compIndex, sources));
|
context.Copy(d, context.TextureQuerySize(type, flags, setAndBinding, compIndex, sources));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TexQuery.TexHeaderTextureType:
|
case TexQuery.TexHeaderTextureType:
|
||||||
binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
setAndBinding = isBindless ? default : context.ResourceManager.GetTextureOrImageBinding(
|
||||||
Instruction.TextureQuerySamples,
|
Instruction.TextureQuerySamples,
|
||||||
type,
|
type,
|
||||||
TextureFormat.Unknown,
|
TextureFormat.Unknown,
|
||||||
@@ -1171,7 +1171,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
|
|
||||||
if (d != null)
|
if (d != null)
|
||||||
{
|
{
|
||||||
context.Copy(d, context.TextureQuerySamples(type, flags, binding, sources));
|
context.Copy(d, context.TextureQuerySamples(type, flags, setAndBinding, sources));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1191,7 +1191,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
Operand[] dests,
|
Operand[] dests,
|
||||||
Operand[] sources)
|
Operand[] sources)
|
||||||
{
|
{
|
||||||
int binding = flags.HasFlag(TextureFlags.Bindless) ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
SetBindingPair setAndBinding = flags.HasFlag(TextureFlags.Bindless) ? default : context.ResourceManager.GetTextureOrImageBinding(
|
||||||
Instruction.TextureSample,
|
Instruction.TextureSample,
|
||||||
type,
|
type,
|
||||||
TextureFormat.Unknown,
|
TextureFormat.Unknown,
|
||||||
@@ -1199,7 +1199,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
TextureOperation.DefaultCbufSlot,
|
TextureOperation.DefaultCbufSlot,
|
||||||
handle);
|
handle);
|
||||||
|
|
||||||
context.TextureSample(type, flags, binding, componentMask, dests, sources);
|
context.TextureSample(type, flags, setAndBinding, componentMask, dests, sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SamplerType ConvertSamplerType(TexDim dimensions)
|
private static SamplerType ConvertSamplerType(TexDim dimensions)
|
||||||
|
@@ -8,7 +8,9 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
|||||||
public TextureFormat Format { get; set; }
|
public TextureFormat Format { get; set; }
|
||||||
public TextureFlags Flags { get; private set; }
|
public TextureFlags Flags { get; private set; }
|
||||||
|
|
||||||
|
public int Set { get; private set; }
|
||||||
public int Binding { get; private set; }
|
public int Binding { get; private set; }
|
||||||
|
public int SamplerSet { get; private set; }
|
||||||
public int SamplerBinding { get; private set; }
|
public int SamplerBinding { get; private set; }
|
||||||
|
|
||||||
public TextureOperation(
|
public TextureOperation(
|
||||||
@@ -16,6 +18,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
|||||||
SamplerType type,
|
SamplerType type,
|
||||||
TextureFormat format,
|
TextureFormat format,
|
||||||
TextureFlags flags,
|
TextureFlags flags,
|
||||||
|
int set,
|
||||||
int binding,
|
int binding,
|
||||||
int compIndex,
|
int compIndex,
|
||||||
Operand[] dests,
|
Operand[] dests,
|
||||||
@@ -24,24 +27,28 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
|||||||
Type = type;
|
Type = type;
|
||||||
Format = format;
|
Format = format;
|
||||||
Flags = flags;
|
Flags = flags;
|
||||||
|
Set = set;
|
||||||
Binding = binding;
|
Binding = binding;
|
||||||
|
SamplerSet = -1;
|
||||||
SamplerBinding = -1;
|
SamplerBinding = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TurnIntoArray(int binding)
|
public void TurnIntoArray(SetBindingPair setAndBinding)
|
||||||
{
|
{
|
||||||
Flags &= ~TextureFlags.Bindless;
|
Flags &= ~TextureFlags.Bindless;
|
||||||
Binding = binding;
|
Set = setAndBinding.SetIndex;
|
||||||
|
Binding = setAndBinding.Binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TurnIntoArray(int textureBinding, int samplerBinding)
|
public void TurnIntoArray(SetBindingPair textureSetAndBinding, SetBindingPair samplerSetAndBinding)
|
||||||
{
|
{
|
||||||
TurnIntoArray(textureBinding);
|
TurnIntoArray(textureSetAndBinding);
|
||||||
|
|
||||||
SamplerBinding = samplerBinding;
|
SamplerSet = samplerSetAndBinding.SetIndex;
|
||||||
|
SamplerBinding = samplerSetAndBinding.Binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBinding(int binding)
|
public void SetBinding(SetBindingPair setAndBinding)
|
||||||
{
|
{
|
||||||
if ((Flags & TextureFlags.Bindless) != 0)
|
if ((Flags & TextureFlags.Bindless) != 0)
|
||||||
{
|
{
|
||||||
@@ -50,7 +57,8 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
|||||||
RemoveSource(0);
|
RemoveSource(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Binding = binding;
|
Set = setAndBinding.SetIndex;
|
||||||
|
Binding = setAndBinding.Binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetLodLevelFlag()
|
public void SetLodLevelFlag()
|
||||||
|
4
ryujinx/src/Ryujinx.Graphics.Shader/SetBindingPair.cs
Normal file
4
ryujinx/src/Ryujinx.Graphics.Shader/SetBindingPair.cs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
namespace Ryujinx.Graphics.Shader
|
||||||
|
{
|
||||||
|
public readonly record struct SetBindingPair(int SetIndex, int Binding);
|
||||||
|
}
|
@@ -8,7 +8,9 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||||||
public TextureFormat Format { get; }
|
public TextureFormat Format { get; }
|
||||||
public TextureFlags Flags { get; }
|
public TextureFlags Flags { get; }
|
||||||
|
|
||||||
|
public int Set { get; }
|
||||||
public int Binding { get; }
|
public int Binding { get; }
|
||||||
|
public int SamplerSet { get; }
|
||||||
public int SamplerBinding { get; }
|
public int SamplerBinding { get; }
|
||||||
|
|
||||||
public bool IsSeparate => SamplerBinding >= 0;
|
public bool IsSeparate => SamplerBinding >= 0;
|
||||||
@@ -18,7 +20,9 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||||||
SamplerType type,
|
SamplerType type,
|
||||||
TextureFormat format,
|
TextureFormat format,
|
||||||
TextureFlags flags,
|
TextureFlags flags,
|
||||||
|
int set,
|
||||||
int binding,
|
int binding,
|
||||||
|
int samplerSet,
|
||||||
int samplerBinding,
|
int samplerBinding,
|
||||||
int index,
|
int index,
|
||||||
params IAstNode[] sources) : base(inst, StorageKind.None, false, index, sources, sources.Length)
|
params IAstNode[] sources) : base(inst, StorageKind.None, false, index, sources, sources.Length)
|
||||||
@@ -26,8 +30,20 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||||||
Type = type;
|
Type = type;
|
||||||
Format = format;
|
Format = format;
|
||||||
Flags = flags;
|
Flags = flags;
|
||||||
|
Set = set;
|
||||||
Binding = binding;
|
Binding = binding;
|
||||||
|
SamplerSet = samplerSet;
|
||||||
SamplerBinding = samplerBinding;
|
SamplerBinding = samplerBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SetBindingPair GetTextureSetAndBinding()
|
||||||
|
{
|
||||||
|
return new SetBindingPair(Set, Binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SetBindingPair GetSamplerSetAndBinding()
|
||||||
|
{
|
||||||
|
return new SetBindingPair(SamplerSet, SamplerBinding);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,15 +6,15 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||||||
{
|
{
|
||||||
private readonly Dictionary<int, BufferDefinition> _constantBuffers;
|
private readonly Dictionary<int, BufferDefinition> _constantBuffers;
|
||||||
private readonly Dictionary<int, BufferDefinition> _storageBuffers;
|
private readonly Dictionary<int, BufferDefinition> _storageBuffers;
|
||||||
private readonly Dictionary<int, TextureDefinition> _textures;
|
private readonly Dictionary<SetBindingPair, TextureDefinition> _textures;
|
||||||
private readonly Dictionary<int, TextureDefinition> _images;
|
private readonly Dictionary<SetBindingPair, TextureDefinition> _images;
|
||||||
private readonly Dictionary<int, MemoryDefinition> _localMemories;
|
private readonly Dictionary<int, MemoryDefinition> _localMemories;
|
||||||
private readonly Dictionary<int, MemoryDefinition> _sharedMemories;
|
private readonly Dictionary<int, MemoryDefinition> _sharedMemories;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, BufferDefinition> ConstantBuffers => _constantBuffers;
|
public IReadOnlyDictionary<int, BufferDefinition> ConstantBuffers => _constantBuffers;
|
||||||
public IReadOnlyDictionary<int, BufferDefinition> StorageBuffers => _storageBuffers;
|
public IReadOnlyDictionary<int, BufferDefinition> StorageBuffers => _storageBuffers;
|
||||||
public IReadOnlyDictionary<int, TextureDefinition> Textures => _textures;
|
public IReadOnlyDictionary<SetBindingPair, TextureDefinition> Textures => _textures;
|
||||||
public IReadOnlyDictionary<int, TextureDefinition> Images => _images;
|
public IReadOnlyDictionary<SetBindingPair, TextureDefinition> Images => _images;
|
||||||
public IReadOnlyDictionary<int, MemoryDefinition> LocalMemories => _localMemories;
|
public IReadOnlyDictionary<int, MemoryDefinition> LocalMemories => _localMemories;
|
||||||
public IReadOnlyDictionary<int, MemoryDefinition> SharedMemories => _sharedMemories;
|
public IReadOnlyDictionary<int, MemoryDefinition> SharedMemories => _sharedMemories;
|
||||||
|
|
||||||
@@ -22,8 +22,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||||||
{
|
{
|
||||||
_constantBuffers = new Dictionary<int, BufferDefinition>();
|
_constantBuffers = new Dictionary<int, BufferDefinition>();
|
||||||
_storageBuffers = new Dictionary<int, BufferDefinition>();
|
_storageBuffers = new Dictionary<int, BufferDefinition>();
|
||||||
_textures = new Dictionary<int, TextureDefinition>();
|
_textures = new Dictionary<SetBindingPair, TextureDefinition>();
|
||||||
_images = new Dictionary<int, TextureDefinition>();
|
_images = new Dictionary<SetBindingPair, TextureDefinition>();
|
||||||
_localMemories = new Dictionary<int, MemoryDefinition>();
|
_localMemories = new Dictionary<int, MemoryDefinition>();
|
||||||
_sharedMemories = new Dictionary<int, MemoryDefinition>();
|
_sharedMemories = new Dictionary<int, MemoryDefinition>();
|
||||||
}
|
}
|
||||||
@@ -40,12 +40,12 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||||||
|
|
||||||
public void AddOrUpdateTexture(TextureDefinition definition)
|
public void AddOrUpdateTexture(TextureDefinition definition)
|
||||||
{
|
{
|
||||||
_textures[definition.Binding] = definition;
|
_textures[new(definition.Set, definition.Binding)] = definition;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddOrUpdateImage(TextureDefinition definition)
|
public void AddOrUpdateImage(TextureDefinition definition)
|
||||||
{
|
{
|
||||||
_images[definition.Binding] = definition;
|
_images[new(definition.Set, definition.Binding)] = definition;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int AddLocalMemory(MemoryDefinition definition)
|
public int AddLocalMemory(MemoryDefinition definition)
|
||||||
|
@@ -169,7 +169,17 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||||||
|
|
||||||
AstTextureOperation GetAstTextureOperation(TextureOperation texOp)
|
AstTextureOperation GetAstTextureOperation(TextureOperation texOp)
|
||||||
{
|
{
|
||||||
return new AstTextureOperation(inst, texOp.Type, texOp.Format, texOp.Flags, texOp.Binding, texOp.SamplerBinding, texOp.Index, sources);
|
return new AstTextureOperation(
|
||||||
|
inst,
|
||||||
|
texOp.Type,
|
||||||
|
texOp.Format,
|
||||||
|
texOp.Flags,
|
||||||
|
texOp.Set,
|
||||||
|
texOp.Binding,
|
||||||
|
texOp.SamplerSet,
|
||||||
|
texOp.SamplerBinding,
|
||||||
|
texOp.Index,
|
||||||
|
sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
int componentsCount = BitOperations.PopCount((uint)operation.Index);
|
int componentsCount = BitOperations.PopCount((uint)operation.Index);
|
||||||
|
@@ -4,6 +4,7 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
{
|
{
|
||||||
// New fields should be added to the end of the struct to keep disk shader cache compatibility.
|
// New fields should be added to the end of the struct to keep disk shader cache compatibility.
|
||||||
|
|
||||||
|
public readonly int Set;
|
||||||
public readonly int Binding;
|
public readonly int Binding;
|
||||||
|
|
||||||
public readonly SamplerType Type;
|
public readonly SamplerType Type;
|
||||||
@@ -18,6 +19,7 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
public readonly TextureUsageFlags Flags;
|
public readonly TextureUsageFlags Flags;
|
||||||
|
|
||||||
public TextureDescriptor(
|
public TextureDescriptor(
|
||||||
|
int set,
|
||||||
int binding,
|
int binding,
|
||||||
SamplerType type,
|
SamplerType type,
|
||||||
TextureFormat format,
|
TextureFormat format,
|
||||||
@@ -27,6 +29,7 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
bool separate,
|
bool separate,
|
||||||
TextureUsageFlags flags)
|
TextureUsageFlags flags)
|
||||||
{
|
{
|
||||||
|
Set = set;
|
||||||
Binding = binding;
|
Binding = binding;
|
||||||
Type = type;
|
Type = type;
|
||||||
Format = format;
|
Format = format;
|
||||||
|
@@ -124,7 +124,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
this.TextureSample(
|
this.TextureSample(
|
||||||
SamplerType.TextureBuffer,
|
SamplerType.TextureBuffer,
|
||||||
TextureFlags.IntCoords,
|
TextureFlags.IntCoords,
|
||||||
ResourceManager.Reservations.IndexBufferTextureBinding,
|
ResourceManager.Reservations.GetIndexBufferTextureSetAndBinding(),
|
||||||
1,
|
1,
|
||||||
new[] { vertexIndexVr },
|
new[] { vertexIndexVr },
|
||||||
new[] { this.IAdd(ibBaseOffset, outputVertexOffset) });
|
new[] { this.IAdd(ibBaseOffset, outputVertexOffset) });
|
||||||
@@ -145,7 +145,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
this.TextureSample(
|
this.TextureSample(
|
||||||
SamplerType.TextureBuffer,
|
SamplerType.TextureBuffer,
|
||||||
TextureFlags.IntCoords,
|
TextureFlags.IntCoords,
|
||||||
ResourceManager.Reservations.TopologyRemapBufferTextureBinding,
|
ResourceManager.Reservations.GetTopologyRemapBufferTextureSetAndBinding(),
|
||||||
1,
|
1,
|
||||||
new[] { vertexIndex },
|
new[] { vertexIndex },
|
||||||
new[] { this.IAdd(baseVertex, Const(index)) });
|
new[] { this.IAdd(baseVertex, Const(index)) });
|
||||||
|
@@ -618,12 +618,21 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
SamplerType type,
|
SamplerType type,
|
||||||
TextureFormat format,
|
TextureFormat format,
|
||||||
TextureFlags flags,
|
TextureFlags flags,
|
||||||
int binding,
|
SetBindingPair setAndBinding,
|
||||||
Operand[] sources)
|
Operand[] sources)
|
||||||
{
|
{
|
||||||
Operand dest = Local();
|
Operand dest = Local();
|
||||||
|
|
||||||
context.Add(new TextureOperation(Instruction.ImageAtomic, type, format, flags, binding, 0, new[] { dest }, sources));
|
context.Add(new TextureOperation(
|
||||||
|
Instruction.ImageAtomic,
|
||||||
|
type,
|
||||||
|
format,
|
||||||
|
flags,
|
||||||
|
setAndBinding.SetIndex,
|
||||||
|
setAndBinding.Binding,
|
||||||
|
0,
|
||||||
|
new[] { dest },
|
||||||
|
sources));
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
@@ -633,12 +642,21 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
SamplerType type,
|
SamplerType type,
|
||||||
TextureFormat format,
|
TextureFormat format,
|
||||||
TextureFlags flags,
|
TextureFlags flags,
|
||||||
int binding,
|
SetBindingPair setAndBinding,
|
||||||
int compMask,
|
int compMask,
|
||||||
Operand[] dests,
|
Operand[] dests,
|
||||||
Operand[] sources)
|
Operand[] sources)
|
||||||
{
|
{
|
||||||
context.Add(new TextureOperation(Instruction.ImageLoad, type, format, flags, binding, compMask, dests, sources));
|
context.Add(new TextureOperation(
|
||||||
|
Instruction.ImageLoad,
|
||||||
|
type,
|
||||||
|
format,
|
||||||
|
flags,
|
||||||
|
setAndBinding.SetIndex,
|
||||||
|
setAndBinding.Binding,
|
||||||
|
compMask,
|
||||||
|
dests,
|
||||||
|
sources));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ImageStore(
|
public static void ImageStore(
|
||||||
@@ -646,10 +664,19 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
SamplerType type,
|
SamplerType type,
|
||||||
TextureFormat format,
|
TextureFormat format,
|
||||||
TextureFlags flags,
|
TextureFlags flags,
|
||||||
int binding,
|
SetBindingPair setAndBinding,
|
||||||
Operand[] sources)
|
Operand[] sources)
|
||||||
{
|
{
|
||||||
context.Add(new TextureOperation(Instruction.ImageStore, type, format, flags, binding, 0, null, sources));
|
context.Add(new TextureOperation(
|
||||||
|
Instruction.ImageStore,
|
||||||
|
type,
|
||||||
|
format,
|
||||||
|
flags,
|
||||||
|
setAndBinding.SetIndex,
|
||||||
|
setAndBinding.Binding,
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
sources));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand IsNan(this EmitterContext context, Operand a, Instruction fpType = Instruction.FP32)
|
public static Operand IsNan(this EmitterContext context, Operand a, Instruction fpType = Instruction.FP32)
|
||||||
@@ -718,13 +745,22 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
this EmitterContext context,
|
this EmitterContext context,
|
||||||
SamplerType type,
|
SamplerType type,
|
||||||
TextureFlags flags,
|
TextureFlags flags,
|
||||||
int binding,
|
SetBindingPair setAndBinding,
|
||||||
int compIndex,
|
int compIndex,
|
||||||
Operand[] sources)
|
Operand[] sources)
|
||||||
{
|
{
|
||||||
Operand dest = Local();
|
Operand dest = Local();
|
||||||
|
|
||||||
context.Add(new TextureOperation(Instruction.Lod, type, TextureFormat.Unknown, flags, binding, compIndex, new[] { dest }, sources));
|
context.Add(new TextureOperation(
|
||||||
|
Instruction.Lod,
|
||||||
|
type,
|
||||||
|
TextureFormat.Unknown,
|
||||||
|
flags,
|
||||||
|
setAndBinding.SetIndex,
|
||||||
|
setAndBinding.Binding,
|
||||||
|
compIndex,
|
||||||
|
new[] { dest },
|
||||||
|
sources));
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
@@ -889,24 +925,42 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
this EmitterContext context,
|
this EmitterContext context,
|
||||||
SamplerType type,
|
SamplerType type,
|
||||||
TextureFlags flags,
|
TextureFlags flags,
|
||||||
int binding,
|
SetBindingPair setAndBinding,
|
||||||
int compMask,
|
int compMask,
|
||||||
Operand[] dests,
|
Operand[] dests,
|
||||||
Operand[] sources)
|
Operand[] sources)
|
||||||
{
|
{
|
||||||
context.Add(new TextureOperation(Instruction.TextureSample, type, TextureFormat.Unknown, flags, binding, compMask, dests, sources));
|
context.Add(new TextureOperation(
|
||||||
|
Instruction.TextureSample,
|
||||||
|
type,
|
||||||
|
TextureFormat.Unknown,
|
||||||
|
flags,
|
||||||
|
setAndBinding.SetIndex,
|
||||||
|
setAndBinding.Binding,
|
||||||
|
compMask,
|
||||||
|
dests,
|
||||||
|
sources));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand TextureQuerySamples(
|
public static Operand TextureQuerySamples(
|
||||||
this EmitterContext context,
|
this EmitterContext context,
|
||||||
SamplerType type,
|
SamplerType type,
|
||||||
TextureFlags flags,
|
TextureFlags flags,
|
||||||
int binding,
|
SetBindingPair setAndBinding,
|
||||||
Operand[] sources)
|
Operand[] sources)
|
||||||
{
|
{
|
||||||
Operand dest = Local();
|
Operand dest = Local();
|
||||||
|
|
||||||
context.Add(new TextureOperation(Instruction.TextureQuerySamples, type, TextureFormat.Unknown, flags, binding, 0, new[] { dest }, sources));
|
context.Add(new TextureOperation(
|
||||||
|
Instruction.TextureQuerySamples,
|
||||||
|
type,
|
||||||
|
TextureFormat.Unknown,
|
||||||
|
flags,
|
||||||
|
setAndBinding.SetIndex,
|
||||||
|
setAndBinding.Binding,
|
||||||
|
0,
|
||||||
|
new[] { dest },
|
||||||
|
sources));
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
@@ -915,13 +969,22 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
this EmitterContext context,
|
this EmitterContext context,
|
||||||
SamplerType type,
|
SamplerType type,
|
||||||
TextureFlags flags,
|
TextureFlags flags,
|
||||||
int binding,
|
SetBindingPair setAndBinding,
|
||||||
int compIndex,
|
int compIndex,
|
||||||
Operand[] sources)
|
Operand[] sources)
|
||||||
{
|
{
|
||||||
Operand dest = Local();
|
Operand dest = Local();
|
||||||
|
|
||||||
context.Add(new TextureOperation(Instruction.TextureQuerySize, type, TextureFormat.Unknown, flags, binding, compIndex, new[] { dest }, sources));
|
context.Add(new TextureOperation(
|
||||||
|
Instruction.TextureQuerySize,
|
||||||
|
type,
|
||||||
|
TextureFormat.Unknown,
|
||||||
|
flags,
|
||||||
|
setAndBinding.SetIndex,
|
||||||
|
setAndBinding.Binding,
|
||||||
|
compIndex,
|
||||||
|
new[] { dest },
|
||||||
|
sources));
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
@@ -38,6 +38,12 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
// If we can't do bindless elimination, remove the texture operation.
|
// If we can't do bindless elimination, remove the texture operation.
|
||||||
// Set any destination variables to zero.
|
// Set any destination variables to zero.
|
||||||
|
|
||||||
|
string typeName = texOp.Inst.IsImage()
|
||||||
|
? texOp.Type.ToGlslImageType(texOp.Format.GetComponentType())
|
||||||
|
: texOp.Type.ToGlslTextureType();
|
||||||
|
|
||||||
|
gpuAccessor.Log($"Failed to find handle source for bindless access of type \"{typeName}\".");
|
||||||
|
|
||||||
for (int destIndex = 0; destIndex < texOp.DestsCount; destIndex++)
|
for (int destIndex = 0; destIndex < texOp.DestsCount; destIndex++)
|
||||||
{
|
{
|
||||||
block.Operations.AddBefore(node, new Operation(Instruction.Copy, texOp.GetDest(destIndex), OperandHelper.Const(0)));
|
block.Operations.AddBefore(node, new Operation(Instruction.Copy, texOp.GetDest(destIndex), OperandHelper.Const(0)));
|
||||||
@@ -62,17 +68,22 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand nvHandle = texOp.GetSource(0);
|
Operand bindlessHandle = texOp.GetSource(0);
|
||||||
|
|
||||||
if (nvHandle.AsgOp is not Operation handleOp ||
|
if (bindlessHandle.AsgOp is PhiNode phi)
|
||||||
handleOp.Inst != Instruction.Load ||
|
|
||||||
(handleOp.StorageKind != StorageKind.Input && handleOp.StorageKind != StorageKind.StorageBuffer))
|
|
||||||
{
|
{
|
||||||
// Right now, we only allow bindless access when the handle comes from a shader input or storage buffer.
|
for (int srcIndex = 0; srcIndex < phi.SourcesCount; srcIndex++)
|
||||||
// This is an artificial limitation to prevent it from being used in cases where it
|
{
|
||||||
// would have a large performance impact of loading all textures in the pool.
|
Operand phiSource = phi.GetSource(srcIndex);
|
||||||
// It might be removed in the future, if we can mitigate the performance impact.
|
|
||||||
|
|
||||||
|
if (phiSource.AsgOp is not PhiNode && !IsBindlessAccessAllowed(phiSource))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!IsBindlessAccessAllowed(bindlessHandle))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,8 +91,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
Operand samplerHandle = OperandHelper.Local();
|
Operand samplerHandle = OperandHelper.Local();
|
||||||
Operand textureIndex = OperandHelper.Local();
|
Operand textureIndex = OperandHelper.Local();
|
||||||
|
|
||||||
block.Operations.AddBefore(node, new Operation(Instruction.BitwiseAnd, textureHandle, nvHandle, OperandHelper.Const(0xfffff)));
|
block.Operations.AddBefore(node, new Operation(Instruction.BitwiseAnd, textureHandle, bindlessHandle, OperandHelper.Const(0xfffff)));
|
||||||
block.Operations.AddBefore(node, new Operation(Instruction.ShiftRightU32, samplerHandle, nvHandle, OperandHelper.Const(20)));
|
block.Operations.AddBefore(node, new Operation(Instruction.ShiftRightU32, samplerHandle, bindlessHandle, OperandHelper.Const(20)));
|
||||||
|
|
||||||
int texturePoolLength = Math.Max(BindlessToArray.MinimumArrayLength, gpuAccessor.QueryTextureArrayLengthFromPool());
|
int texturePoolLength = Math.Max(BindlessToArray.MinimumArrayLength, gpuAccessor.QueryTextureArrayLengthFromPool());
|
||||||
|
|
||||||
@@ -91,7 +102,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
|
|
||||||
bool hasSampler = !texOp.Inst.IsImage();
|
bool hasSampler = !texOp.Inst.IsImage();
|
||||||
|
|
||||||
int textureBinding = resourceManager.GetTextureOrImageBinding(
|
SetBindingPair textureSetAndBinding = resourceManager.GetTextureOrImageBinding(
|
||||||
texOp.Inst,
|
texOp.Inst,
|
||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
@@ -111,7 +122,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
|
|
||||||
texOp.InsertSource(1, samplerIndex);
|
texOp.InsertSource(1, samplerIndex);
|
||||||
|
|
||||||
int samplerBinding = resourceManager.GetTextureOrImageBinding(
|
SetBindingPair samplerSetAndBinding = resourceManager.GetTextureOrImageBinding(
|
||||||
texOp.Inst,
|
texOp.Inst,
|
||||||
SamplerType.None,
|
SamplerType.None,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
@@ -120,11 +131,35 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
TextureHandle.PackOffsets(0, 0, TextureHandleType.Direct),
|
TextureHandle.PackOffsets(0, 0, TextureHandleType.Direct),
|
||||||
samplerPoolLength);
|
samplerPoolLength);
|
||||||
|
|
||||||
texOp.TurnIntoArray(textureBinding, samplerBinding);
|
texOp.TurnIntoArray(textureSetAndBinding, samplerSetAndBinding);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
texOp.TurnIntoArray(textureBinding);
|
texOp.TurnIntoArray(textureSetAndBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsBindlessAccessAllowed(Operand nvHandle)
|
||||||
|
{
|
||||||
|
if (nvHandle.Type == OperandType.ConstantBuffer)
|
||||||
|
{
|
||||||
|
// Bindless access with handles from constant buffer is allowed.
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nvHandle.AsgOp is not Operation handleOp ||
|
||||||
|
handleOp.Inst != Instruction.Load ||
|
||||||
|
(handleOp.StorageKind != StorageKind.Input && handleOp.StorageKind != StorageKind.StorageBuffer))
|
||||||
|
{
|
||||||
|
// Right now, we only allow bindless access when the handle comes from a shader input or storage buffer.
|
||||||
|
// This is an artificial limitation to prevent it from being used in cases where it
|
||||||
|
// would have a large performance impact of loading all textures in the pool.
|
||||||
|
// It might be removed in the future, if we can mitigate the performance impact.
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -445,7 +480,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int binding = resourceManager.GetTextureOrImageBinding(
|
SetBindingPair setAndBinding = resourceManager.GetTextureOrImageBinding(
|
||||||
texOp.Inst,
|
texOp.Inst,
|
||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
@@ -453,7 +488,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
cbufSlot,
|
cbufSlot,
|
||||||
cbufOffset);
|
cbufOffset);
|
||||||
|
|
||||||
texOp.SetBinding(binding);
|
texOp.SetBinding(setAndBinding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -221,7 +221,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
|
|
||||||
private static void TurnIntoArray(ResourceManager resourceManager, TextureOperation texOp, int cbufSlot, int handleIndex, int length)
|
private static void TurnIntoArray(ResourceManager resourceManager, TextureOperation texOp, int cbufSlot, int handleIndex, int length)
|
||||||
{
|
{
|
||||||
int binding = resourceManager.GetTextureOrImageBinding(
|
SetBindingPair setAndBinding = resourceManager.GetTextureOrImageBinding(
|
||||||
texOp.Inst,
|
texOp.Inst,
|
||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
@@ -230,7 +230,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
handleIndex,
|
handleIndex,
|
||||||
length);
|
length);
|
||||||
|
|
||||||
texOp.TurnIntoArray(binding);
|
texOp.TurnIntoArray(setAndBinding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,8 +20,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
private readonly ShaderStage _stage;
|
private readonly ShaderStage _stage;
|
||||||
private readonly string _stagePrefix;
|
private readonly string _stagePrefix;
|
||||||
|
|
||||||
private readonly int[] _cbSlotToBindingMap;
|
private readonly SetBindingPair[] _cbSlotToBindingMap;
|
||||||
private readonly int[] _sbSlotToBindingMap;
|
private readonly SetBindingPair[] _sbSlotToBindingMap;
|
||||||
private uint _sbSlotWritten;
|
private uint _sbSlotWritten;
|
||||||
|
|
||||||
private readonly Dictionary<int, int> _sbSlots;
|
private readonly Dictionary<int, int> _sbSlots;
|
||||||
@@ -33,6 +33,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
|
|
||||||
private struct TextureMeta
|
private struct TextureMeta
|
||||||
{
|
{
|
||||||
|
public int Set;
|
||||||
public int Binding;
|
public int Binding;
|
||||||
public bool AccurateType;
|
public bool AccurateType;
|
||||||
public SamplerType Type;
|
public SamplerType Type;
|
||||||
@@ -64,10 +65,10 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
_stage = stage;
|
_stage = stage;
|
||||||
_stagePrefix = GetShaderStagePrefix(stage);
|
_stagePrefix = GetShaderStagePrefix(stage);
|
||||||
|
|
||||||
_cbSlotToBindingMap = new int[18];
|
_cbSlotToBindingMap = new SetBindingPair[18];
|
||||||
_sbSlotToBindingMap = new int[16];
|
_sbSlotToBindingMap = new SetBindingPair[16];
|
||||||
_cbSlotToBindingMap.AsSpan().Fill(-1);
|
_cbSlotToBindingMap.AsSpan().Fill(new(-1, -1));
|
||||||
_sbSlotToBindingMap.AsSpan().Fill(-1);
|
_sbSlotToBindingMap.AsSpan().Fill(new(-1, -1));
|
||||||
|
|
||||||
_sbSlots = new();
|
_sbSlots = new();
|
||||||
_sbSlotsReverse = new();
|
_sbSlotsReverse = new();
|
||||||
@@ -146,16 +147,16 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
|
|
||||||
public int GetConstantBufferBinding(int slot)
|
public int GetConstantBufferBinding(int slot)
|
||||||
{
|
{
|
||||||
int binding = _cbSlotToBindingMap[slot];
|
SetBindingPair setAndBinding = _cbSlotToBindingMap[slot];
|
||||||
if (binding < 0)
|
if (setAndBinding.Binding < 0)
|
||||||
{
|
{
|
||||||
binding = _gpuAccessor.CreateConstantBufferBinding(slot);
|
setAndBinding = _gpuAccessor.CreateConstantBufferBinding(slot);
|
||||||
_cbSlotToBindingMap[slot] = binding;
|
_cbSlotToBindingMap[slot] = setAndBinding;
|
||||||
string slotNumber = slot.ToString(CultureInfo.InvariantCulture);
|
string slotNumber = slot.ToString(CultureInfo.InvariantCulture);
|
||||||
AddNewConstantBuffer(binding, $"{_stagePrefix}_c{slotNumber}");
|
AddNewConstantBuffer(setAndBinding.SetIndex, setAndBinding.Binding, $"{_stagePrefix}_c{slotNumber}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return binding;
|
return setAndBinding.Binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetStorageBufferBinding(int sbCbSlot, int sbCbOffset, bool write, out int binding)
|
public bool TryGetStorageBufferBinding(int sbCbSlot, int sbCbOffset, bool write, out int binding)
|
||||||
@@ -166,14 +167,14 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
binding = _sbSlotToBindingMap[slot];
|
SetBindingPair setAndBinding = _sbSlotToBindingMap[slot];
|
||||||
|
|
||||||
if (binding < 0)
|
if (setAndBinding.Binding < 0)
|
||||||
{
|
{
|
||||||
binding = _gpuAccessor.CreateStorageBufferBinding(slot);
|
setAndBinding = _gpuAccessor.CreateStorageBufferBinding(slot);
|
||||||
_sbSlotToBindingMap[slot] = binding;
|
_sbSlotToBindingMap[slot] = setAndBinding;
|
||||||
string slotNumber = slot.ToString(CultureInfo.InvariantCulture);
|
string slotNumber = slot.ToString(CultureInfo.InvariantCulture);
|
||||||
AddNewStorageBuffer(binding, $"{_stagePrefix}_s{slotNumber}");
|
AddNewStorageBuffer(setAndBinding.SetIndex, setAndBinding.Binding, $"{_stagePrefix}_s{slotNumber}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write)
|
if (write)
|
||||||
@@ -181,6 +182,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
_sbSlotWritten |= 1u << slot;
|
_sbSlotWritten |= 1u << slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding = setAndBinding.Binding;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +210,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
{
|
{
|
||||||
for (slot = 0; slot < _cbSlotToBindingMap.Length; slot++)
|
for (slot = 0; slot < _cbSlotToBindingMap.Length; slot++)
|
||||||
{
|
{
|
||||||
if (_cbSlotToBindingMap[slot] == binding)
|
if (_cbSlotToBindingMap[slot].Binding == binding)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -218,7 +220,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetTextureOrImageBinding(
|
public SetBindingPair GetTextureOrImageBinding(
|
||||||
Instruction inst,
|
Instruction inst,
|
||||||
SamplerType type,
|
SamplerType type,
|
||||||
TextureFormat format,
|
TextureFormat format,
|
||||||
@@ -240,7 +242,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
format = TextureFormat.Unknown;
|
format = TextureFormat.Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
int binding = GetTextureOrImageBinding(
|
SetBindingPair setAndBinding = GetTextureOrImageBinding(
|
||||||
cbufSlot,
|
cbufSlot,
|
||||||
handle,
|
handle,
|
||||||
arrayLength,
|
arrayLength,
|
||||||
@@ -255,10 +257,10 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
|
|
||||||
_gpuAccessor.RegisterTexture(handle, cbufSlot);
|
_gpuAccessor.RegisterTexture(handle, cbufSlot);
|
||||||
|
|
||||||
return binding;
|
return setAndBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetTextureOrImageBinding(
|
private SetBindingPair GetTextureOrImageBinding(
|
||||||
int cbufSlot,
|
int cbufSlot,
|
||||||
int handle,
|
int handle,
|
||||||
int arrayLength,
|
int arrayLength,
|
||||||
@@ -311,21 +313,38 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
UsageFlags = usageFlags,
|
UsageFlags = usageFlags,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int setIndex;
|
||||||
int binding;
|
int binding;
|
||||||
|
|
||||||
if (dict.TryGetValue(info, out var existingMeta))
|
if (dict.TryGetValue(info, out var existingMeta))
|
||||||
{
|
{
|
||||||
dict[info] = MergeTextureMeta(meta, existingMeta);
|
dict[info] = MergeTextureMeta(meta, existingMeta);
|
||||||
|
setIndex = existingMeta.Set;
|
||||||
binding = existingMeta.Binding;
|
binding = existingMeta.Binding;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool isBuffer = (type & SamplerType.Mask) == SamplerType.TextureBuffer;
|
if (arrayLength > 1 && (setIndex = _gpuAccessor.CreateExtraSet()) >= 0)
|
||||||
|
{
|
||||||
|
// We reserved an "extra set" for the array.
|
||||||
|
// In this case the binding is always the first one (0).
|
||||||
|
// Using separate sets for array is better as we need to do less descriptor set updates.
|
||||||
|
|
||||||
binding = isImage
|
binding = 0;
|
||||||
? _gpuAccessor.CreateImageBinding(arrayLength, isBuffer)
|
}
|
||||||
: _gpuAccessor.CreateTextureBinding(arrayLength, isBuffer);
|
else
|
||||||
|
{
|
||||||
|
bool isBuffer = (type & SamplerType.Mask) == SamplerType.TextureBuffer;
|
||||||
|
|
||||||
|
SetBindingPair setAndBinding = isImage
|
||||||
|
? _gpuAccessor.CreateImageBinding(arrayLength, isBuffer)
|
||||||
|
: _gpuAccessor.CreateTextureBinding(arrayLength, isBuffer);
|
||||||
|
|
||||||
|
setIndex = setAndBinding.SetIndex;
|
||||||
|
binding = setAndBinding.Binding;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta.Set = setIndex;
|
||||||
meta.Binding = binding;
|
meta.Binding = binding;
|
||||||
|
|
||||||
dict.Add(info, meta);
|
dict.Add(info, meta);
|
||||||
@@ -355,7 +374,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
}
|
}
|
||||||
|
|
||||||
var definition = new TextureDefinition(
|
var definition = new TextureDefinition(
|
||||||
isImage ? 3 : 2,
|
setIndex,
|
||||||
binding,
|
binding,
|
||||||
arrayLength,
|
arrayLength,
|
||||||
separate,
|
separate,
|
||||||
@@ -373,11 +392,12 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
Properties.AddOrUpdateTexture(definition);
|
Properties.AddOrUpdateTexture(definition);
|
||||||
}
|
}
|
||||||
|
|
||||||
return binding;
|
return new SetBindingPair(setIndex, binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TextureMeta MergeTextureMeta(TextureMeta meta, TextureMeta existingMeta)
|
private static TextureMeta MergeTextureMeta(TextureMeta meta, TextureMeta existingMeta)
|
||||||
{
|
{
|
||||||
|
meta.Set = existingMeta.Set;
|
||||||
meta.Binding = existingMeta.Binding;
|
meta.Binding = existingMeta.Binding;
|
||||||
meta.UsageFlags |= existingMeta.UsageFlags;
|
meta.UsageFlags |= existingMeta.UsageFlags;
|
||||||
|
|
||||||
@@ -440,11 +460,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
|
|
||||||
for (int slot = 0; slot < _cbSlotToBindingMap.Length; slot++)
|
for (int slot = 0; slot < _cbSlotToBindingMap.Length; slot++)
|
||||||
{
|
{
|
||||||
int binding = _cbSlotToBindingMap[slot];
|
SetBindingPair setAndBinding = _cbSlotToBindingMap[slot];
|
||||||
|
|
||||||
if (binding >= 0 && _usedConstantBufferBindings.Contains(binding))
|
if (setAndBinding.Binding >= 0 && _usedConstantBufferBindings.Contains(setAndBinding.Binding))
|
||||||
{
|
{
|
||||||
descriptors[descriptorIndex++] = new BufferDescriptor(binding, slot);
|
descriptors[descriptorIndex++] = new BufferDescriptor(setAndBinding.SetIndex, setAndBinding.Binding, slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,13 +484,13 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
|
|
||||||
foreach ((int key, int slot) in _sbSlots)
|
foreach ((int key, int slot) in _sbSlots)
|
||||||
{
|
{
|
||||||
int binding = _sbSlotToBindingMap[slot];
|
SetBindingPair setAndBinding = _sbSlotToBindingMap[slot];
|
||||||
|
|
||||||
if (binding >= 0)
|
if (setAndBinding.Binding >= 0)
|
||||||
{
|
{
|
||||||
(int sbCbSlot, int sbCbOffset) = UnpackSbCbInfo(key);
|
(int sbCbSlot, int sbCbOffset) = UnpackSbCbInfo(key);
|
||||||
BufferUsageFlags flags = (_sbSlotWritten & (1u << slot)) != 0 ? BufferUsageFlags.Write : BufferUsageFlags.None;
|
BufferUsageFlags flags = (_sbSlotWritten & (1u << slot)) != 0 ? BufferUsageFlags.Write : BufferUsageFlags.None;
|
||||||
descriptors[descriptorIndex++] = new BufferDescriptor(binding, slot, sbCbSlot, sbCbOffset, flags);
|
descriptors[descriptorIndex++] = new BufferDescriptor(setAndBinding.SetIndex, setAndBinding.Binding, slot, sbCbSlot, sbCbOffset, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,6 +527,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
}
|
}
|
||||||
|
|
||||||
descriptors.Add(new TextureDescriptor(
|
descriptors.Add(new TextureDescriptor(
|
||||||
|
meta.Set,
|
||||||
meta.Binding,
|
meta.Binding,
|
||||||
meta.Type,
|
meta.Type,
|
||||||
info.Format,
|
info.Format,
|
||||||
@@ -527,6 +548,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
}
|
}
|
||||||
|
|
||||||
descriptors.Add(new TextureDescriptor(
|
descriptors.Add(new TextureDescriptor(
|
||||||
|
meta.Set,
|
||||||
meta.Binding,
|
meta.Binding,
|
||||||
meta.Type,
|
meta.Type,
|
||||||
info.Format,
|
info.Format,
|
||||||
@@ -587,24 +609,24 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddNewConstantBuffer(int binding, string name)
|
private void AddNewConstantBuffer(int setIndex, int binding, string name)
|
||||||
{
|
{
|
||||||
StructureType type = new(new[]
|
StructureType type = new(new[]
|
||||||
{
|
{
|
||||||
new StructureField(AggregateType.Array | AggregateType.Vector4 | AggregateType.FP32, "data", Constants.ConstantBufferSize / 16),
|
new StructureField(AggregateType.Array | AggregateType.Vector4 | AggregateType.FP32, "data", Constants.ConstantBufferSize / 16),
|
||||||
});
|
});
|
||||||
|
|
||||||
Properties.AddOrUpdateConstantBuffer(new(BufferLayout.Std140, 0, binding, name, type));
|
Properties.AddOrUpdateConstantBuffer(new(BufferLayout.Std140, setIndex, binding, name, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddNewStorageBuffer(int binding, string name)
|
private void AddNewStorageBuffer(int setIndex, int binding, string name)
|
||||||
{
|
{
|
||||||
StructureType type = new(new[]
|
StructureType type = new(new[]
|
||||||
{
|
{
|
||||||
new StructureField(AggregateType.Array | AggregateType.U32, "data", 0),
|
new StructureField(AggregateType.Array | AggregateType.U32, "data", 0),
|
||||||
});
|
});
|
||||||
|
|
||||||
Properties.AddOrUpdateStorageBuffer(new(BufferLayout.Std430, 1, binding, name, type));
|
Properties.AddOrUpdateStorageBuffer(new(BufferLayout.Std430, setIndex, binding, name, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetShaderStagePrefix(ShaderStage stage)
|
public static string GetShaderStagePrefix(ShaderStage stage)
|
||||||
|
@@ -11,6 +11,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
|
|
||||||
public const int MaxVertexBufferTextures = 32;
|
public const int MaxVertexBufferTextures = 32;
|
||||||
|
|
||||||
|
private const int TextureSetIndex = 2; // TODO: Get from GPU accessor.
|
||||||
|
|
||||||
public int VertexInfoConstantBufferBinding { get; }
|
public int VertexInfoConstantBufferBinding { get; }
|
||||||
public int VertexOutputStorageBufferBinding { get; }
|
public int VertexOutputStorageBufferBinding { get; }
|
||||||
public int GeometryVertexOutputStorageBufferBinding { get; }
|
public int GeometryVertexOutputStorageBufferBinding { get; }
|
||||||
@@ -163,6 +165,21 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
return _vertexBufferTextureBaseBinding + vaLocation;
|
return _vertexBufferTextureBaseBinding + vaLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SetBindingPair GetVertexBufferTextureSetAndBinding(int vaLocation)
|
||||||
|
{
|
||||||
|
return new SetBindingPair(TextureSetIndex, GetVertexBufferTextureBinding(vaLocation));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SetBindingPair GetIndexBufferTextureSetAndBinding()
|
||||||
|
{
|
||||||
|
return new SetBindingPair(TextureSetIndex, IndexBufferTextureBinding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SetBindingPair GetTopologyRemapBufferTextureSetAndBinding()
|
||||||
|
{
|
||||||
|
return new SetBindingPair(TextureSetIndex, TopologyRemapBufferTextureBinding);
|
||||||
|
}
|
||||||
|
|
||||||
internal bool TryGetOffset(StorageKind storageKind, int location, int component, out int offset)
|
internal bool TryGetOffset(StorageKind storageKind, int location, int component, out int offset)
|
||||||
{
|
{
|
||||||
return _offsets.TryGetValue(new IoDefinition(storageKind, IoVariable.UserDefined, location, component), out offset);
|
return _offsets.TryGetValue(new IoDefinition(storageKind, IoVariable.UserDefined, location, component), out offset);
|
||||||
|
@@ -182,6 +182,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags,
|
texOp.Flags,
|
||||||
|
texOp.Set,
|
||||||
texOp.Binding,
|
texOp.Binding,
|
||||||
index,
|
index,
|
||||||
new[] { coordSize },
|
new[] { coordSize },
|
||||||
@@ -251,6 +252,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags,
|
texOp.Flags,
|
||||||
|
texOp.Set,
|
||||||
texOp.Binding,
|
texOp.Binding,
|
||||||
index,
|
index,
|
||||||
new[] { coordSize },
|
new[] { coordSize },
|
||||||
@@ -471,6 +473,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags & ~(TextureFlags.Offset | TextureFlags.Offsets),
|
texOp.Flags & ~(TextureFlags.Offset | TextureFlags.Offsets),
|
||||||
|
texOp.Set,
|
||||||
texOp.Binding,
|
texOp.Binding,
|
||||||
1 << 3, // W component: i=0, j=0
|
1 << 3, // W component: i=0, j=0
|
||||||
new[] { dests[destIndex++] },
|
new[] { dests[destIndex++] },
|
||||||
@@ -527,6 +530,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags & ~(TextureFlags.Offset | TextureFlags.Offsets),
|
texOp.Flags & ~(TextureFlags.Offset | TextureFlags.Offsets),
|
||||||
|
texOp.Set,
|
||||||
texOp.Binding,
|
texOp.Binding,
|
||||||
componentIndex,
|
componentIndex,
|
||||||
dests,
|
dests,
|
||||||
@@ -573,6 +577,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags,
|
texOp.Flags,
|
||||||
|
texOp.Set,
|
||||||
texOp.Binding,
|
texOp.Binding,
|
||||||
index,
|
index,
|
||||||
new[] { texSizes[index] },
|
new[] { texSizes[index] },
|
||||||
@@ -603,6 +608,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags,
|
texOp.Flags,
|
||||||
|
texOp.Set,
|
||||||
texOp.Binding,
|
texOp.Binding,
|
||||||
0,
|
0,
|
||||||
new[] { lod },
|
new[] { lod },
|
||||||
@@ -633,6 +639,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags,
|
texOp.Flags,
|
||||||
|
texOp.Set,
|
||||||
texOp.Binding,
|
texOp.Binding,
|
||||||
index,
|
index,
|
||||||
new[] { texSizes[index] },
|
new[] { texSizes[index] },
|
||||||
|
@@ -54,6 +54,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
{
|
{
|
||||||
bool needsSextNorm = context.Definitions.IsAttributePackedRgb10A2Signed(location);
|
bool needsSextNorm = context.Definitions.IsAttributePackedRgb10A2Signed(location);
|
||||||
|
|
||||||
|
SetBindingPair setAndBinding = context.ResourceManager.Reservations.GetVertexBufferTextureSetAndBinding(location);
|
||||||
Operand temp = needsSextNorm ? Local() : dest;
|
Operand temp = needsSextNorm ? Local() : dest;
|
||||||
Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, location, 0);
|
Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, location, 0);
|
||||||
|
|
||||||
@@ -62,7 +63,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
SamplerType.TextureBuffer,
|
SamplerType.TextureBuffer,
|
||||||
TextureFormat.Unknown,
|
TextureFormat.Unknown,
|
||||||
TextureFlags.IntCoords,
|
TextureFlags.IntCoords,
|
||||||
context.ResourceManager.Reservations.GetVertexBufferTextureBinding(location),
|
setAndBinding.SetIndex,
|
||||||
|
setAndBinding.Binding,
|
||||||
1 << component,
|
1 << component,
|
||||||
new[] { temp },
|
new[] { temp },
|
||||||
new[] { vertexElemOffset }));
|
new[] { vertexElemOffset }));
|
||||||
@@ -75,6 +77,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
SetBindingPair setAndBinding = context.ResourceManager.Reservations.GetVertexBufferTextureSetAndBinding(location);
|
||||||
Operand temp = component > 0 ? Local() : dest;
|
Operand temp = component > 0 ? Local() : dest;
|
||||||
Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, location, component);
|
Operand vertexElemOffset = GenerateVertexOffset(context.ResourceManager, node, location, component);
|
||||||
|
|
||||||
@@ -83,7 +86,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
SamplerType.TextureBuffer,
|
SamplerType.TextureBuffer,
|
||||||
TextureFormat.Unknown,
|
TextureFormat.Unknown,
|
||||||
TextureFlags.IntCoords,
|
TextureFlags.IntCoords,
|
||||||
context.ResourceManager.Reservations.GetVertexBufferTextureBinding(location),
|
setAndBinding.SetIndex,
|
||||||
|
setAndBinding.Binding,
|
||||||
1,
|
1,
|
||||||
new[] { temp },
|
new[] { temp },
|
||||||
new[] { vertexElemOffset }));
|
new[] { vertexElemOffset }));
|
||||||
|
@@ -412,8 +412,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
|
|
||||||
if (Stage == ShaderStage.Vertex)
|
if (Stage == ShaderStage.Vertex)
|
||||||
{
|
{
|
||||||
int ibBinding = resourceManager.Reservations.IndexBufferTextureBinding;
|
SetBindingPair ibSetAndBinding = resourceManager.Reservations.GetIndexBufferTextureSetAndBinding();
|
||||||
TextureDefinition indexBuffer = new(2, ibBinding, "ib_data", SamplerType.TextureBuffer);
|
TextureDefinition indexBuffer = new(ibSetAndBinding.SetIndex, ibSetAndBinding.Binding, "ib_data", SamplerType.TextureBuffer);
|
||||||
resourceManager.Properties.AddOrUpdateTexture(indexBuffer);
|
resourceManager.Properties.AddOrUpdateTexture(indexBuffer);
|
||||||
|
|
||||||
int inputMap = _program.AttributeUsage.UsedInputAttributes;
|
int inputMap = _program.AttributeUsage.UsedInputAttributes;
|
||||||
@@ -421,8 +421,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
while (inputMap != 0)
|
while (inputMap != 0)
|
||||||
{
|
{
|
||||||
int location = BitOperations.TrailingZeroCount(inputMap);
|
int location = BitOperations.TrailingZeroCount(inputMap);
|
||||||
int binding = resourceManager.Reservations.GetVertexBufferTextureBinding(location);
|
SetBindingPair setAndBinding = resourceManager.Reservations.GetVertexBufferTextureSetAndBinding(location);
|
||||||
TextureDefinition vaBuffer = new(2, binding, $"vb_data{location}", SamplerType.TextureBuffer);
|
TextureDefinition vaBuffer = new(setAndBinding.SetIndex, setAndBinding.Binding, $"vb_data{location}", SamplerType.TextureBuffer);
|
||||||
resourceManager.Properties.AddOrUpdateTexture(vaBuffer);
|
resourceManager.Properties.AddOrUpdateTexture(vaBuffer);
|
||||||
|
|
||||||
inputMap &= ~(1 << location);
|
inputMap &= ~(1 << location);
|
||||||
@@ -430,8 +430,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
}
|
}
|
||||||
else if (Stage == ShaderStage.Geometry)
|
else if (Stage == ShaderStage.Geometry)
|
||||||
{
|
{
|
||||||
int trbBinding = resourceManager.Reservations.TopologyRemapBufferTextureBinding;
|
SetBindingPair trbSetAndBinding = resourceManager.Reservations.GetTopologyRemapBufferTextureSetAndBinding();
|
||||||
TextureDefinition remapBuffer = new(2, trbBinding, "trb_data", SamplerType.TextureBuffer);
|
TextureDefinition remapBuffer = new(trbSetAndBinding.SetIndex, trbSetAndBinding.Binding, "trb_data", SamplerType.TextureBuffer);
|
||||||
resourceManager.Properties.AddOrUpdateTexture(remapBuffer);
|
resourceManager.Properties.AddOrUpdateTexture(remapBuffer);
|
||||||
|
|
||||||
int geometryVbOutputSbBinding = resourceManager.Reservations.GeometryVertexOutputStorageBufferBinding;
|
int geometryVbOutputSbBinding = resourceManager.Reservations.GeometryVertexOutputStorageBufferBinding;
|
||||||
|
@@ -69,17 +69,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private record struct ArrayRef<T>
|
private readonly record struct ArrayRef<T>(ShaderStage Stage, T Array);
|
||||||
{
|
|
||||||
public ShaderStage Stage;
|
|
||||||
public T Array;
|
|
||||||
|
|
||||||
public ArrayRef(ShaderStage stage, T array)
|
|
||||||
{
|
|
||||||
Stage = stage;
|
|
||||||
Array = array;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly VulkanRenderer _gd;
|
private readonly VulkanRenderer _gd;
|
||||||
private readonly Device _device;
|
private readonly Device _device;
|
||||||
@@ -97,6 +87,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private ArrayRef<TextureArray>[] _textureArrayRefs;
|
private ArrayRef<TextureArray>[] _textureArrayRefs;
|
||||||
private ArrayRef<ImageArray>[] _imageArrayRefs;
|
private ArrayRef<ImageArray>[] _imageArrayRefs;
|
||||||
|
|
||||||
|
private ArrayRef<TextureArray>[] _textureArrayExtraRefs;
|
||||||
|
private ArrayRef<ImageArray>[] _imageArrayExtraRefs;
|
||||||
|
|
||||||
private readonly DescriptorBufferInfo[] _uniformBuffers;
|
private readonly DescriptorBufferInfo[] _uniformBuffers;
|
||||||
private readonly DescriptorBufferInfo[] _storageBuffers;
|
private readonly DescriptorBufferInfo[] _storageBuffers;
|
||||||
private readonly DescriptorImageInfo[] _textures;
|
private readonly DescriptorImageInfo[] _textures;
|
||||||
@@ -152,6 +145,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_textureArrayRefs = Array.Empty<ArrayRef<TextureArray>>();
|
_textureArrayRefs = Array.Empty<ArrayRef<TextureArray>>();
|
||||||
_imageArrayRefs = Array.Empty<ArrayRef<ImageArray>>();
|
_imageArrayRefs = Array.Empty<ArrayRef<ImageArray>>();
|
||||||
|
|
||||||
|
_textureArrayExtraRefs = Array.Empty<ArrayRef<TextureArray>>();
|
||||||
|
_imageArrayExtraRefs = Array.Empty<ArrayRef<ImageArray>>();
|
||||||
|
|
||||||
_uniformBuffers = new DescriptorBufferInfo[Constants.MaxUniformBufferBindings];
|
_uniformBuffers = new DescriptorBufferInfo[Constants.MaxUniformBufferBindings];
|
||||||
_storageBuffers = new DescriptorBufferInfo[Constants.MaxStorageBufferBindings];
|
_storageBuffers = new DescriptorBufferInfo[Constants.MaxStorageBufferBindings];
|
||||||
_textures = new DescriptorImageInfo[Constants.MaxTexturesPerStage];
|
_textures = new DescriptorImageInfo[Constants.MaxTexturesPerStage];
|
||||||
@@ -495,25 +491,39 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public void SetTextureArray(CommandBufferScoped cbs, ShaderStage stage, int binding, ITextureArray array)
|
public void SetTextureArray(CommandBufferScoped cbs, ShaderStage stage, int binding, ITextureArray array)
|
||||||
{
|
{
|
||||||
if (_textureArrayRefs.Length <= binding)
|
ref ArrayRef<TextureArray> arrayRef = ref GetArrayRef(ref _textureArrayRefs, binding, ArrayGrowthSize);
|
||||||
{
|
|
||||||
Array.Resize(ref _textureArrayRefs, binding + ArrayGrowthSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_textureArrayRefs[binding].Stage != stage || _textureArrayRefs[binding].Array != array)
|
if (arrayRef.Stage != stage || arrayRef.Array != array)
|
||||||
{
|
{
|
||||||
if (_textureArrayRefs[binding].Array != null)
|
arrayRef.Array?.DecrementBindCount();
|
||||||
{
|
|
||||||
_textureArrayRefs[binding].Array.Bound = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array is TextureArray textureArray)
|
if (array is TextureArray textureArray)
|
||||||
{
|
{
|
||||||
textureArray.Bound = true;
|
textureArray.IncrementBindCount();
|
||||||
textureArray.QueueWriteToReadBarriers(cbs, stage.ConvertToPipelineStageFlags());
|
textureArray.QueueWriteToReadBarriers(cbs, stage.ConvertToPipelineStageFlags());
|
||||||
}
|
}
|
||||||
|
|
||||||
_textureArrayRefs[binding] = new ArrayRef<TextureArray>(stage, array as TextureArray);
|
arrayRef = new ArrayRef<TextureArray>(stage, array as TextureArray);
|
||||||
|
|
||||||
|
SignalDirty(DirtyFlags.Texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetTextureArraySeparate(CommandBufferScoped cbs, ShaderStage stage, int setIndex, ITextureArray array)
|
||||||
|
{
|
||||||
|
ref ArrayRef<TextureArray> arrayRef = ref GetArrayRef(ref _textureArrayExtraRefs, setIndex - PipelineBase.DescriptorSetLayouts);
|
||||||
|
|
||||||
|
if (arrayRef.Stage != stage || arrayRef.Array != array)
|
||||||
|
{
|
||||||
|
arrayRef.Array?.DecrementBindCount();
|
||||||
|
|
||||||
|
if (array is TextureArray textureArray)
|
||||||
|
{
|
||||||
|
textureArray.IncrementBindCount();
|
||||||
|
textureArray.QueueWriteToReadBarriers(cbs, stage.ConvertToPipelineStageFlags());
|
||||||
|
}
|
||||||
|
|
||||||
|
arrayRef = new ArrayRef<TextureArray>(stage, array as TextureArray);
|
||||||
|
|
||||||
SignalDirty(DirtyFlags.Texture);
|
SignalDirty(DirtyFlags.Texture);
|
||||||
}
|
}
|
||||||
@@ -521,30 +531,56 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public void SetImageArray(CommandBufferScoped cbs, ShaderStage stage, int binding, IImageArray array)
|
public void SetImageArray(CommandBufferScoped cbs, ShaderStage stage, int binding, IImageArray array)
|
||||||
{
|
{
|
||||||
if (_imageArrayRefs.Length <= binding)
|
ref ArrayRef<ImageArray> arrayRef = ref GetArrayRef(ref _imageArrayRefs, binding, ArrayGrowthSize);
|
||||||
{
|
|
||||||
Array.Resize(ref _imageArrayRefs, binding + ArrayGrowthSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_imageArrayRefs[binding].Stage != stage || _imageArrayRefs[binding].Array != array)
|
if (arrayRef.Stage != stage || arrayRef.Array != array)
|
||||||
{
|
{
|
||||||
if (_imageArrayRefs[binding].Array != null)
|
arrayRef.Array?.DecrementBindCount();
|
||||||
{
|
|
||||||
_imageArrayRefs[binding].Array.Bound = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array is ImageArray imageArray)
|
if (array is ImageArray imageArray)
|
||||||
{
|
{
|
||||||
imageArray.Bound = true;
|
imageArray.IncrementBindCount();
|
||||||
imageArray.QueueWriteToReadBarriers(cbs, stage.ConvertToPipelineStageFlags());
|
imageArray.QueueWriteToReadBarriers(cbs, stage.ConvertToPipelineStageFlags());
|
||||||
}
|
}
|
||||||
|
|
||||||
_imageArrayRefs[binding] = new ArrayRef<ImageArray>(stage, array as ImageArray);
|
arrayRef = new ArrayRef<ImageArray>(stage, array as ImageArray);
|
||||||
|
|
||||||
SignalDirty(DirtyFlags.Image);
|
SignalDirty(DirtyFlags.Image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetImageArraySeparate(CommandBufferScoped cbs, ShaderStage stage, int setIndex, IImageArray array)
|
||||||
|
{
|
||||||
|
ref ArrayRef<ImageArray> arrayRef = ref GetArrayRef(ref _imageArrayExtraRefs, setIndex - PipelineBase.DescriptorSetLayouts);
|
||||||
|
|
||||||
|
if (arrayRef.Stage != stage || arrayRef.Array != array)
|
||||||
|
{
|
||||||
|
arrayRef.Array?.DecrementBindCount();
|
||||||
|
|
||||||
|
if (array is ImageArray imageArray)
|
||||||
|
{
|
||||||
|
imageArray.IncrementBindCount();
|
||||||
|
imageArray.QueueWriteToReadBarriers(cbs, stage.ConvertToPipelineStageFlags());
|
||||||
|
}
|
||||||
|
|
||||||
|
arrayRef = new ArrayRef<ImageArray>(stage, array as ImageArray);
|
||||||
|
|
||||||
|
SignalDirty(DirtyFlags.Image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ref ArrayRef<T> GetArrayRef<T>(ref ArrayRef<T>[] array, int index, int growthSize = 1)
|
||||||
|
{
|
||||||
|
ArgumentOutOfRangeException.ThrowIfNegative(index);
|
||||||
|
|
||||||
|
if (array.Length <= index)
|
||||||
|
{
|
||||||
|
Array.Resize(ref array, index + growthSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref array[index];
|
||||||
|
}
|
||||||
|
|
||||||
public void SetUniformBuffers(CommandBuffer commandBuffer, ReadOnlySpan<BufferAssignment> buffers)
|
public void SetUniformBuffers(CommandBuffer commandBuffer, ReadOnlySpan<BufferAssignment> buffers)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < buffers.Length; i++)
|
for (int i = 0; i < buffers.Length; i++)
|
||||||
@@ -594,31 +630,40 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var program = _program;
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Uniform))
|
if (_dirty.HasFlag(DirtyFlags.Uniform))
|
||||||
{
|
{
|
||||||
if (_program.UsePushDescriptors)
|
if (program.UsePushDescriptors)
|
||||||
{
|
{
|
||||||
UpdateAndBindUniformBufferPd(cbs, pbp);
|
UpdateAndBindUniformBufferPd(cbs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UpdateAndBind(cbs, PipelineBase.UniformSetIndex, pbp);
|
UpdateAndBind(cbs, program, PipelineBase.UniformSetIndex, pbp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Storage))
|
if (_dirty.HasFlag(DirtyFlags.Storage))
|
||||||
{
|
{
|
||||||
UpdateAndBind(cbs, PipelineBase.StorageSetIndex, pbp);
|
UpdateAndBind(cbs, program, PipelineBase.StorageSetIndex, pbp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Texture))
|
if (_dirty.HasFlag(DirtyFlags.Texture))
|
||||||
{
|
{
|
||||||
UpdateAndBind(cbs, PipelineBase.TextureSetIndex, pbp);
|
UpdateAndBind(cbs, program, PipelineBase.TextureSetIndex, pbp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Image))
|
if (_dirty.HasFlag(DirtyFlags.Image))
|
||||||
{
|
{
|
||||||
UpdateAndBind(cbs, PipelineBase.ImageSetIndex, pbp);
|
UpdateAndBind(cbs, program, PipelineBase.ImageSetIndex, pbp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (program.BindingSegments.Length > PipelineBase.DescriptorSetLayouts)
|
||||||
|
{
|
||||||
|
// Program is using extra sets, we need to bind those too.
|
||||||
|
|
||||||
|
BindExtraSets(cbs, program, pbp);
|
||||||
}
|
}
|
||||||
|
|
||||||
_dirty = DirtyFlags.None;
|
_dirty = DirtyFlags.None;
|
||||||
@@ -658,9 +703,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void UpdateAndBind(CommandBufferScoped cbs, int setIndex, PipelineBindPoint pbp)
|
private void UpdateAndBind(CommandBufferScoped cbs, ShaderCollection program, int setIndex, PipelineBindPoint pbp)
|
||||||
{
|
{
|
||||||
var program = _program;
|
|
||||||
var bindingSegments = program.BindingSegments[setIndex];
|
var bindingSegments = program.BindingSegments[setIndex];
|
||||||
|
|
||||||
if (bindingSegments.Length == 0)
|
if (bindingSegments.Length == 0)
|
||||||
@@ -869,7 +913,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void UpdateAndBindUniformBufferPd(CommandBufferScoped cbs, PipelineBindPoint pbp)
|
private void UpdateAndBindUniformBufferPd(CommandBufferScoped cbs)
|
||||||
{
|
{
|
||||||
int sequence = _pdSequence;
|
int sequence = _pdSequence;
|
||||||
var bindingSegments = _program.BindingSegments[PipelineBase.UniformSetIndex];
|
var bindingSegments = _program.BindingSegments[PipelineBase.UniformSetIndex];
|
||||||
@@ -933,6 +977,56 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void BindExtraSets(CommandBufferScoped cbs, ShaderCollection program, PipelineBindPoint pbp)
|
||||||
|
{
|
||||||
|
for (int setIndex = PipelineBase.DescriptorSetLayouts; setIndex < program.BindingSegments.Length; setIndex++)
|
||||||
|
{
|
||||||
|
var bindingSegments = program.BindingSegments[setIndex];
|
||||||
|
|
||||||
|
if (bindingSegments.Length == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceBindingSegment segment = bindingSegments[0];
|
||||||
|
|
||||||
|
if (segment.IsArray)
|
||||||
|
{
|
||||||
|
DescriptorSet[] sets = null;
|
||||||
|
|
||||||
|
if (segment.Type == ResourceType.Texture ||
|
||||||
|
segment.Type == ResourceType.Sampler ||
|
||||||
|
segment.Type == ResourceType.TextureAndSampler ||
|
||||||
|
segment.Type == ResourceType.BufferTexture)
|
||||||
|
{
|
||||||
|
sets = _textureArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts].Array.GetDescriptorSets(
|
||||||
|
_device,
|
||||||
|
cbs,
|
||||||
|
_templateUpdater,
|
||||||
|
program,
|
||||||
|
setIndex,
|
||||||
|
_dummyTexture,
|
||||||
|
_dummySampler);
|
||||||
|
}
|
||||||
|
else if (segment.Type == ResourceType.Image || segment.Type == ResourceType.BufferImage)
|
||||||
|
{
|
||||||
|
sets = _imageArrayExtraRefs[setIndex - PipelineBase.DescriptorSetLayouts].Array.GetDescriptorSets(
|
||||||
|
_device,
|
||||||
|
cbs,
|
||||||
|
_templateUpdater,
|
||||||
|
program,
|
||||||
|
setIndex,
|
||||||
|
_dummyTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sets != null)
|
||||||
|
{
|
||||||
|
_gd.Api.CmdBindDescriptorSets(cbs.CommandBuffer, pbp, _program.PipelineLayout, (uint)setIndex, 1, sets, 0, ReadOnlySpan<uint>.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SignalCommandBufferChange()
|
public void SignalCommandBufferChange()
|
||||||
{
|
{
|
||||||
_updateDescriptorCacheCbIndex = true;
|
_updateDescriptorCacheCbIndex = true;
|
||||||
|
@@ -2,6 +2,7 @@ using Ryujinx.Graphics.GAL;
|
|||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
@@ -24,12 +25,18 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private HashSet<TextureStorage> _storages;
|
private HashSet<TextureStorage> _storages;
|
||||||
|
|
||||||
|
private DescriptorSet[] _cachedDescriptorSets;
|
||||||
|
|
||||||
private int _cachedCommandBufferIndex;
|
private int _cachedCommandBufferIndex;
|
||||||
private int _cachedSubmissionCount;
|
private int _cachedSubmissionCount;
|
||||||
|
|
||||||
|
private ShaderCollection _cachedDscProgram;
|
||||||
|
private int _cachedDscSetIndex;
|
||||||
|
private int _cachedDscIndex;
|
||||||
|
|
||||||
private readonly bool _isBuffer;
|
private readonly bool _isBuffer;
|
||||||
|
|
||||||
public bool Bound;
|
private int _bindCount;
|
||||||
|
|
||||||
public ImageArray(VulkanRenderer gd, int size, bool isBuffer)
|
public ImageArray(VulkanRenderer gd, int size, bool isBuffer)
|
||||||
{
|
{
|
||||||
@@ -97,8 +104,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
_cachedCommandBufferIndex = -1;
|
_cachedCommandBufferIndex = -1;
|
||||||
_storages = null;
|
_storages = null;
|
||||||
|
_cachedDescriptorSets = null;
|
||||||
|
|
||||||
_gd.PipelineInternal.ForceImageDirty();
|
if (_bindCount != 0)
|
||||||
|
{
|
||||||
|
_gd.PipelineInternal.ForceImageDirty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags)
|
public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags)
|
||||||
@@ -175,5 +186,65 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
return bufferTextures;
|
return bufferTextures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DescriptorSet[] GetDescriptorSets(
|
||||||
|
Device device,
|
||||||
|
CommandBufferScoped cbs,
|
||||||
|
DescriptorSetTemplateUpdater templateUpdater,
|
||||||
|
ShaderCollection program,
|
||||||
|
int setIndex,
|
||||||
|
TextureView dummyTexture)
|
||||||
|
{
|
||||||
|
if (_cachedDescriptorSets != null)
|
||||||
|
{
|
||||||
|
// We still need to ensure the current command buffer holds a reference to all used textures.
|
||||||
|
|
||||||
|
if (!_isBuffer)
|
||||||
|
{
|
||||||
|
GetImageInfos(_gd, cbs, dummyTexture);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GetBufferViews(cbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _cachedDescriptorSets;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cachedDscProgram?.ReleaseManualDescriptorSetCollection(_cachedDscSetIndex, _cachedDscIndex);
|
||||||
|
var dsc = program.GetNewManualDescriptorSetCollection(cbs.CommandBufferIndex, setIndex, out _cachedDscIndex).Get(cbs);
|
||||||
|
|
||||||
|
DescriptorSetTemplate template = program.Templates[setIndex];
|
||||||
|
|
||||||
|
DescriptorSetTemplateWriter tu = templateUpdater.Begin(template);
|
||||||
|
|
||||||
|
if (!_isBuffer)
|
||||||
|
{
|
||||||
|
tu.Push(GetImageInfos(_gd, cbs, dummyTexture));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tu.Push(GetBufferViews(cbs));
|
||||||
|
}
|
||||||
|
|
||||||
|
var sets = dsc.GetSets();
|
||||||
|
templateUpdater.Commit(_gd, device, sets[0]);
|
||||||
|
_cachedDescriptorSets = sets;
|
||||||
|
_cachedDscProgram = program;
|
||||||
|
_cachedDscSetIndex = setIndex;
|
||||||
|
|
||||||
|
return sets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IncrementBindCount()
|
||||||
|
{
|
||||||
|
_bindCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DecrementBindCount()
|
||||||
|
{
|
||||||
|
int newBindCount = --_bindCount;
|
||||||
|
Debug.Assert(newBindCount >= 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user