mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Started the report of wgpu
This commit is contained in:
parent
ab5f0df06b
commit
806f240eb5
397
Cargo.lock
generated
397
Cargo.lock
generated
@ -203,6 +203,15 @@ dependencies = [
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ash"
|
||||
version = "0.31.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c69a8137596e84c22d57f3da1b5de1d4230b1742a710091c85f4d7ce50f00f38"
|
||||
dependencies = [
|
||||
"libloading 0.6.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "assets_manager"
|
||||
version = "0.4.4"
|
||||
@ -358,6 +367,21 @@ dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
@ -764,6 +788,12 @@ dependencies = [
|
||||
"walkdir 0.1.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "copyless"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536"
|
||||
|
||||
[[package]]
|
||||
name = "copypasta"
|
||||
version = "0.7.1"
|
||||
@ -1205,6 +1235,17 @@ dependencies = [
|
||||
"sct",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "d3d12"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a60cceb22c7c53035f8980524fdc7f17cf49681a3c154e6757d30afbec6ec4"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libloading 0.6.7",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "daggy"
|
||||
version = "0.5.0"
|
||||
@ -1861,6 +1902,152 @@ dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gfx-auxil"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07cd956b592970f08545b9325b87580eb95a51843b6f39da27b8667fec1a1216"
|
||||
dependencies = [
|
||||
"fxhash",
|
||||
"gfx-hal",
|
||||
"spirv_cross",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gfx-backend-dx11"
|
||||
version = "0.6.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54b43f06089866bdffe59b5a6801022c86b74d2c1dd28940a9cf301d3d014fbc"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
"gfx-auxil",
|
||||
"gfx-hal",
|
||||
"libloading 0.6.7",
|
||||
"log",
|
||||
"parking_lot 0.11.1",
|
||||
"range-alloc",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"spirv_cross",
|
||||
"thunderdome",
|
||||
"winapi 0.3.9",
|
||||
"wio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gfx-backend-dx12"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "375014deed24d76b03604736dd899f0925158a1a96db90cbefb9cce070f71af7"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-set",
|
||||
"bitflags",
|
||||
"d3d12",
|
||||
"gfx-auxil",
|
||||
"gfx-hal",
|
||||
"log",
|
||||
"range-alloc",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"spirv_cross",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gfx-backend-empty"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2085227c12b78f6657a900c829f2d0deb46a9be3eaf86844fde263cdc218f77c"
|
||||
dependencies = [
|
||||
"gfx-hal",
|
||||
"log",
|
||||
"raw-window-handle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gfx-backend-metal"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "273d60d5207f96d99e0d11d0718995f67e56533a9df1444d83baf787f4c3cb32"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
"block",
|
||||
"cocoa-foundation",
|
||||
"copyless",
|
||||
"foreign-types",
|
||||
"gfx-auxil",
|
||||
"gfx-hal",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"metal",
|
||||
"objc",
|
||||
"parking_lot 0.11.1",
|
||||
"range-alloc",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"spirv_cross",
|
||||
"storage-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gfx-backend-vulkan"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a3a63cf61067a09b7d1ac480af3cb2ae0c5ede5bed294607bbd814cb1666c45"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"ash",
|
||||
"byteorder",
|
||||
"core-graphics-types",
|
||||
"gfx-hal",
|
||||
"inplace_it",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"objc",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"winapi 0.3.9",
|
||||
"x11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gfx-descriptor"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd8c7afcd000f279d541a490e27117e61037537279b9342279abf4938fe60c6b"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"fxhash",
|
||||
"gfx-hal",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gfx-hal"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18d0754f5b7a43915fd7466883b2d1bb0800d7cc4609178d0b27bf143b9e5123"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"raw-window-handle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gfx-memory"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dccdda5d2b39412f4ca2cb15c70b5a82783a86b0606f5e985342754c8ed88f05"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"fxhash",
|
||||
"gfx-hal",
|
||||
"log",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gfx_core"
|
||||
version = "0.9.2"
|
||||
@ -2432,6 +2619,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inplace_it"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90953f308a79fe6d62a4643e51f848fbfddcd05975a38e69fdf4ab86a7baf7ca"
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.9"
|
||||
@ -2832,6 +3025,20 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "metal"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c4e8a431536529327e28c9ba6992f2cb0c15d4222f0602a16e6d7695ff3bccf"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"block",
|
||||
"cocoa-foundation",
|
||||
"foreign-types",
|
||||
"log",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minifb"
|
||||
version = "0.19.1"
|
||||
@ -2947,6 +3154,20 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238"
|
||||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0873deb76cf44b7454fba7b2ba6a89d3de70c08aceffd2c489379b3d9d08e661"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"fxhash",
|
||||
"log",
|
||||
"num-traits",
|
||||
"spirv_headers",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-dialog"
|
||||
version = "0.5.5"
|
||||
@ -3387,6 +3608,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
"objc_exception",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3400,6 +3622,15 @@ dependencies = [
|
||||
"objc_id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_exception"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_id"
|
||||
version = "0.1.1"
|
||||
@ -4018,6 +4249,12 @@ dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "range-alloc"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6"
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.3.3"
|
||||
@ -4793,6 +5030,27 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spirv_cross"
|
||||
version = "0.22.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ebd49af36be83ecd6290b57147e2a0e26145b832634b17146d934b197ca3713"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spirv_headers"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f5b132530b1ac069df335577e3581765995cba5a13995cdbbdbc8fb057c532c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
@ -4871,6 +5129,15 @@ version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
|
||||
|
||||
[[package]]
|
||||
name = "storage-map"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418bb14643aa55a7841d5303f72cf512cfb323b8cc221d51580500a1ca75206c"
|
||||
dependencies = [
|
||||
"lock_api 0.4.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "str-buf"
|
||||
version = "1.0.5"
|
||||
@ -4971,6 +5238,18 @@ dependencies = [
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.69",
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
@ -5055,6 +5334,12 @@ dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thunderdome"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7572415bd688d401c52f6e36f4c8e805b9ae1622619303b9fa835d531db0acae"
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.43"
|
||||
@ -5339,6 +5624,12 @@ dependencies = [
|
||||
"nom 5.1.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typed-arena"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.13.0"
|
||||
@ -5810,6 +6101,7 @@ dependencies = [
|
||||
"dot_vox",
|
||||
"enum-iterator",
|
||||
"euc",
|
||||
"futures",
|
||||
"gfx",
|
||||
"gfx_device_gl",
|
||||
"gfx_gl",
|
||||
@ -5855,9 +6147,11 @@ dependencies = [
|
||||
"veloren-server",
|
||||
"veloren-voxygen-anim",
|
||||
"veloren-world",
|
||||
"wgpu",
|
||||
"window_clipboard 0.2.0",
|
||||
"winit",
|
||||
"winres",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6408,9 +6702,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.50"
|
||||
version = "0.3.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be"
|
||||
checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
@ -6436,6 +6730,65 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wgpu"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "991903e4c9f5b7319732b30a3d0339e27a51ea992cea22769b5f6c7f7076af6d"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"futures",
|
||||
"gfx-backend-vulkan",
|
||||
"js-sys",
|
||||
"objc",
|
||||
"parking_lot 0.11.1",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
"typed-arena",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"wgpu-core",
|
||||
"wgpu-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-core"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea487deeae90e06d77eb8e6cef945247774e7c0a0a226d238b31e90633594365"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
"copyless",
|
||||
"fxhash",
|
||||
"gfx-backend-dx11",
|
||||
"gfx-backend-dx12",
|
||||
"gfx-backend-empty",
|
||||
"gfx-backend-metal",
|
||||
"gfx-backend-vulkan",
|
||||
"gfx-descriptor",
|
||||
"gfx-hal",
|
||||
"gfx-memory",
|
||||
"naga",
|
||||
"parking_lot 0.11.1",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"wgpu-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-types"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e3529528e608b54838ee618c3923b0f46e6db0334cfc6c42a16cf4ceb3bdb57"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.1.0"
|
||||
@ -6564,6 +6917,15 @@ dependencies = [
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wio"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5"
|
||||
dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ws2_32-sys"
|
||||
version = "0.2.1"
|
||||
@ -6583,6 +6945,16 @@ dependencies = [
|
||||
"tap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11"
|
||||
version = "2.18.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ecd092546cb16f25783a5451538e73afc8d32e242648d54f4ae5459ba1e773"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11-clipboard"
|
||||
version = "0.5.1"
|
||||
@ -6700,3 +7072,24 @@ checksum = "0de7bff972b4f2a06c85f6d8454b09df153af7e3a4ec2aac81db1b105b684ddb"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6580539ad917b7c026220c4b3f2c08d52ce54d6ce0dc491e66002e35388fab46"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.26",
|
||||
"syn 1.0.69",
|
||||
"synstructure",
|
||||
]
|
||||
|
@ -22,14 +22,13 @@ runtimeLibs = ["libGL", "xorg.libX11", "xorg.libXcursor", "xorg.libXrandr", "xor
|
||||
buildInputs = ["xorg.libxcb"]
|
||||
|
||||
[features]
|
||||
gl = ["gfx_device_gl", "gfx_gl"]
|
||||
hot-anim = ["anim/use-dyn-lib"]
|
||||
singleplayer = ["server"]
|
||||
simd = ["vek/platform_intrinsics"]
|
||||
tracy = ["common/tracy", "common-ecs/tracy", "common-frontend/tracy", "common-net/tracy", "common-systems/tracy", "common-state/tracy", "client/tracy"]
|
||||
plugins = ["client/plugins"]
|
||||
|
||||
default = ["gl", "singleplayer", "native-dialog", "plugins", "simd"]
|
||||
default = ["singleplayer", "native-dialog", "plugins", "simd"]
|
||||
|
||||
[dependencies]
|
||||
client = {package = "veloren-client", path = "../client"}
|
||||
@ -51,6 +50,8 @@ gfx_gl = {version = "0.6.1", optional = true}
|
||||
glutin = "0.26.0"
|
||||
old_school_gfx_glutin_ext = "0.26"
|
||||
winit = {version = "0.24.0", features = ["serde"]}
|
||||
wgpu = "0.6.0"
|
||||
zerocopy = "0.3.0"
|
||||
|
||||
# Ui
|
||||
conrod_core = {git = "https://gitlab.com/veloren/conrod.git", branch="copypasta_0.7"}
|
||||
@ -87,8 +88,7 @@ crossbeam-channel = "0.5"
|
||||
directories-next = "2.0"
|
||||
dot_vox = "4.0"
|
||||
enum-iterator = "0.6"
|
||||
strum = "0.20"
|
||||
strum_macros = "0.20"
|
||||
futures = "0.3"
|
||||
glsl-include = "0.3.1"
|
||||
guillotiere = "0.6"
|
||||
hashbrown = {version = "0.9", features = ["rayon", "serde", "nightly"]}
|
||||
@ -101,6 +101,8 @@ rand = "0.8"
|
||||
rodio = {version = "0.13", default-features = false, features = ["vorbis"]}
|
||||
ron = {version = "0.6", default-features = false}
|
||||
serde = {version = "1.0", features = [ "rc", "derive" ]}
|
||||
strum = "0.20"
|
||||
strum_macros = "0.20"
|
||||
treeculler = "0.2"
|
||||
tokio = { version = "1", default-features = false, features = ["rt-multi-thread"] }
|
||||
num_cpus = "1.0"
|
||||
|
@ -2,7 +2,14 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![allow(clippy::option_map_unit_fn)]
|
||||
#![deny(clippy::clone_on_ref_ptr)]
|
||||
#![feature(array_map, bool_to_option, const_generics, drain_filter, once_cell)]
|
||||
#![feature(
|
||||
array_map,
|
||||
bool_to_option,
|
||||
const_generics,
|
||||
drain_filter,
|
||||
once_cell,
|
||||
trait_alias
|
||||
)]
|
||||
#![recursion_limit = "2048"]
|
||||
|
||||
#[macro_use]
|
||||
|
52
voxygen/src/render/buffer.rs
Normal file
52
voxygen/src/render/buffer.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use super::RenderError;
|
||||
use wgpu::util::DeviceExt;
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Buffer<T: Copy + AsBytes> {
|
||||
pub buf: wgpu::Buffer,
|
||||
// bytes
|
||||
count: usize,
|
||||
phantom_data: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: Copy + AsBytes> Buffer<T> {
|
||||
pub fn new(device: &mut wgpu::Device, cap: usize, usage: wgpu::BufferUsage) -> Self {
|
||||
Self {
|
||||
buf: device.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: None,
|
||||
mapped_at_creation: false,
|
||||
size: cap,
|
||||
usage: usage | wgpu::BufferUsage::MAP_WRITE,
|
||||
}),
|
||||
count: 0,
|
||||
phantom_data: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_data(device: &mut wgpu::Device, usage: wgpu::BufferUsage, data: &[T]) -> Self {
|
||||
let contents = data.as_bytes();
|
||||
|
||||
Self {
|
||||
buf: device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: None,
|
||||
contents,
|
||||
usage: usage | wgpu::BufferUsage::MAP_WRITE,
|
||||
}),
|
||||
count: data.len(),
|
||||
phantom_data: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
vals: &[T],
|
||||
offset: usize,
|
||||
) {
|
||||
queue.write_buffer(&self.buf, offset, vals.as_bytes())
|
||||
}
|
||||
|
||||
pub fn count(&self) -> usize { self.count }
|
||||
}
|
@ -1,36 +1,32 @@
|
||||
use super::{gfx_backend, RenderError};
|
||||
use gfx::{self, traits::FactoryExt};
|
||||
use super::{buffer::Buffer, RenderError};
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
/// A handle to a series of constants sitting on the GPU. This is used to hold
|
||||
/// information used in the rendering process that does not change throughout a
|
||||
/// single render pass.
|
||||
#[derive(Clone)]
|
||||
pub struct Consts<T: Copy + gfx::traits::Pod> {
|
||||
pub buf: gfx::handle::Buffer<gfx_backend::Resources, T>,
|
||||
pub struct Consts<T: Copy + AsBytes> {
|
||||
buf: Buffer<T>,
|
||||
}
|
||||
|
||||
impl<T: Copy + gfx::traits::Pod> Consts<T> {
|
||||
impl<T: Copy + AsBytes> Consts<T> {
|
||||
/// Create a new `Const<T>`.
|
||||
pub fn new(factory: &mut gfx_backend::Factory, len: usize) -> Self {
|
||||
pub fn new(device: &mut wgpu::Device, len: usize) -> Self {
|
||||
Self {
|
||||
buf: factory.create_constant_buffer(len),
|
||||
buf: Buffer::new(device, len, wgpu::BufferUsage::UNIFORM),
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the GPU-side value represented by this constant handle.
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
encoder: &mut gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
vals: &[T],
|
||||
offset: usize,
|
||||
) -> Result<(), RenderError> {
|
||||
if vals.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
encoder
|
||||
.update_buffer(&self.buf, vals, offset)
|
||||
.map_err(RenderError::UpdateError)
|
||||
}
|
||||
self.buf.update(device, queue, vals, offset)
|
||||
}
|
||||
|
||||
pub fn buf(&self) -> &wgpu::Buffer { self.buf.buf }
|
||||
}
|
||||
|
@ -2,73 +2,20 @@
|
||||
/// rendering subsystem.
|
||||
#[derive(Debug)]
|
||||
pub enum RenderError {
|
||||
PipelineError(gfx::PipelineStateError<String>),
|
||||
UpdateError(gfx::UpdateError<usize>),
|
||||
TexUpdateError(gfx::UpdateError<[u16; 3]>),
|
||||
CombinedError(gfx::CombinedError),
|
||||
BufferCreationError(gfx::buffer::CreationError),
|
||||
IncludeError(glsl_include::Error),
|
||||
MappingError(gfx::mapping::Error),
|
||||
CopyError(gfx::CopyError<[u16; 3], usize>),
|
||||
RequestDeviceError(wgpu::RequestDeviceError),
|
||||
MappingError(wgpu::BufferAsyncError),
|
||||
SwapChainError(wgpu::SwapChainError),
|
||||
CustomError(String),
|
||||
CouldNotFindAdapter,
|
||||
}
|
||||
|
||||
impl From<gfx::PipelineStateError<String>> for RenderError {
|
||||
fn from(err: gfx::PipelineStateError<String>) -> Self { Self::PipelineError(err) }
|
||||
impl From<wgpu::RequestDeviceError> for RenderError {
|
||||
fn from(err: wgpu::RequestDeviceError) -> Self { Self::RequestDeviceError(err) }
|
||||
}
|
||||
|
||||
impl From<gfx::PipelineStateError<&str>> for RenderError {
|
||||
fn from(err: gfx::PipelineStateError<&str>) -> Self {
|
||||
match err {
|
||||
gfx::PipelineStateError::DescriptorInit(err) => {
|
||||
gfx::PipelineStateError::DescriptorInit(err)
|
||||
},
|
||||
err => err,
|
||||
impl From<wgpu::BufferAsyncError> for RenderError {
|
||||
fn from(err: wgpu::BufferAsyncError) -> Self { Self::MappingError(err) }
|
||||
}
|
||||
.into()
|
||||
}
|
||||
}
|
||||
impl From<gfx::shade::ProgramError> for RenderError {
|
||||
fn from(err: gfx::shade::ProgramError) -> Self {
|
||||
gfx::PipelineStateError::<String>::Program(err).into()
|
||||
}
|
||||
}
|
||||
impl From<gfx::UpdateError<usize>> for RenderError {
|
||||
fn from(err: gfx::UpdateError<usize>) -> Self { Self::UpdateError(err) }
|
||||
}
|
||||
|
||||
impl From<gfx::UpdateError<[u16; 3]>> for RenderError {
|
||||
fn from(err: gfx::UpdateError<[u16; 3]>) -> Self { Self::TexUpdateError(err) }
|
||||
}
|
||||
|
||||
impl From<gfx::CombinedError> for RenderError {
|
||||
fn from(err: gfx::CombinedError) -> Self { Self::CombinedError(err) }
|
||||
}
|
||||
|
||||
impl From<gfx::TargetViewError> for RenderError {
|
||||
fn from(err: gfx::TargetViewError) -> Self { Self::CombinedError(err.into()) }
|
||||
}
|
||||
|
||||
impl From<gfx::ResourceViewError> for RenderError {
|
||||
fn from(err: gfx::ResourceViewError) -> Self { Self::CombinedError(err.into()) }
|
||||
}
|
||||
|
||||
impl From<gfx::texture::CreationError> for RenderError {
|
||||
fn from(err: gfx::texture::CreationError) -> Self { Self::CombinedError(err.into()) }
|
||||
}
|
||||
|
||||
impl From<gfx::buffer::CreationError> for RenderError {
|
||||
fn from(err: gfx::buffer::CreationError) -> Self { Self::BufferCreationError(err) }
|
||||
}
|
||||
|
||||
impl From<glsl_include::Error> for RenderError {
|
||||
fn from(err: glsl_include::Error) -> Self { Self::IncludeError(err) }
|
||||
}
|
||||
|
||||
impl From<gfx::mapping::Error> for RenderError {
|
||||
fn from(err: gfx::mapping::Error) -> Self { Self::MappingError(err) }
|
||||
}
|
||||
|
||||
impl From<gfx::CopyError<[u16; 3], usize>> for RenderError {
|
||||
fn from(err: gfx::CopyError<[u16; 3], usize>) -> Self { Self::CopyError(err) }
|
||||
impl From<wgpu::SwapChainError> for RenderError {
|
||||
fn from(err: wgpu::SwapChainError) -> Self { Self::SwapChainError(err) }
|
||||
}
|
||||
|
@ -1,34 +1,30 @@
|
||||
use super::{gfx_backend, RenderError};
|
||||
use gfx::{
|
||||
self,
|
||||
buffer::Role,
|
||||
memory::{Bind, Usage},
|
||||
Factory,
|
||||
};
|
||||
use super::{buffer::Buffer, RenderError};
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
/// Represents a mesh that has been sent to the GPU.
|
||||
pub struct Instances<T: Copy + gfx::traits::Pod> {
|
||||
pub ibuf: gfx::handle::Buffer<gfx_backend::Resources, T>,
|
||||
#[derive(Clone)]
|
||||
pub struct Instances<T: Copy + AsBytes> {
|
||||
buf: Buffer<T>,
|
||||
}
|
||||
|
||||
impl<T: Copy + gfx::traits::Pod> Instances<T> {
|
||||
pub fn new(factory: &mut gfx_backend::Factory, len: usize) -> Result<Self, RenderError> {
|
||||
Ok(Self {
|
||||
ibuf: factory
|
||||
.create_buffer(len, Role::Vertex, Usage::Dynamic, Bind::empty())
|
||||
.map_err(RenderError::BufferCreationError)?,
|
||||
})
|
||||
impl<T: Copy + AsBytes> Instances<T> {
|
||||
pub fn new(device: &mut wgpu::Device, len: usize) -> Self {
|
||||
Self {
|
||||
buf: Buffer::new(device, len, wgpu::BufferUsage::VERTEX),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn count(&self) -> usize { self.ibuf.len() }
|
||||
pub fn count(&self) -> usize { self.buf.count() }
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
encoder: &mut gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
||||
instances: &[T],
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
vals: &[T],
|
||||
offset: usize,
|
||||
) -> Result<(), RenderError> {
|
||||
encoder
|
||||
.update_buffer(&self.ibuf, instances, 0)
|
||||
.map_err(RenderError::UpdateError)
|
||||
self.buf.update(device, queue, vals, offset)
|
||||
}
|
||||
|
||||
pub fn buf(&self) -> &wgpu::Buffer { self.buf.buf }
|
||||
}
|
||||
|
@ -1,15 +1,12 @@
|
||||
use super::Pipeline;
|
||||
use super::Vertex;
|
||||
use core::{iter::FromIterator, ops::Range};
|
||||
|
||||
/// A `Vec`-based mesh structure used to store mesh data on the CPU.
|
||||
pub struct Mesh<P: Pipeline> {
|
||||
verts: Vec<P::Vertex>,
|
||||
pub struct Mesh<V: Vertex> {
|
||||
verts: Vec<V>,
|
||||
}
|
||||
|
||||
impl<P: Pipeline> Clone for Mesh<P>
|
||||
where
|
||||
P::Vertex: Clone,
|
||||
{
|
||||
impl<V: Vertex> Clone for Mesh<V> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
verts: self.verts.clone(),
|
||||
@ -17,7 +14,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Pipeline> Mesh<P> {
|
||||
impl<V: Vertex> Mesh<V> {
|
||||
/// Create a new `Mesh`.
|
||||
#[allow(clippy::new_without_default)] // TODO: Pending review in #587
|
||||
pub fn new() -> Self { Self { verts: Vec::new() } }
|
||||
@ -26,23 +23,23 @@ impl<P: Pipeline> Mesh<P> {
|
||||
pub fn clear(&mut self) { self.verts.clear(); }
|
||||
|
||||
/// Get a slice referencing the vertices of this mesh.
|
||||
pub fn vertices(&self) -> &[P::Vertex] { &self.verts }
|
||||
pub fn vertices(&self) -> &[V] { &self.verts }
|
||||
|
||||
/// Get a mutable slice referencing the vertices of this mesh.
|
||||
pub fn vertices_mut(&mut self) -> &mut [P::Vertex] { &mut self.verts }
|
||||
|
||||
/// Push a new vertex onto the end of this mesh.
|
||||
pub fn push(&mut self, vert: P::Vertex) { self.verts.push(vert); }
|
||||
pub fn push(&mut self, vert: V) { self.verts.push(vert); }
|
||||
|
||||
/// Push a new polygon onto the end of this mesh.
|
||||
pub fn push_tri(&mut self, tri: Tri<P>) {
|
||||
pub fn push_tri(&mut self, tri: Tri<V>) {
|
||||
self.verts.push(tri.a);
|
||||
self.verts.push(tri.b);
|
||||
self.verts.push(tri.c);
|
||||
}
|
||||
|
||||
/// Push a new quad onto the end of this mesh.
|
||||
pub fn push_quad(&mut self, quad: Quad<P>) {
|
||||
pub fn push_quad(&mut self, quad: Quad<V>) {
|
||||
// A quad is composed of two triangles. The code below converts the former to
|
||||
// the latter.
|
||||
|
||||
@ -73,10 +70,10 @@ impl<P: Pipeline> Mesh<P> {
|
||||
}
|
||||
|
||||
/// Push the vertices of another mesh onto the end of this mesh.
|
||||
pub fn push_mesh(&mut self, other: &Mesh<P>) { self.verts.extend_from_slice(other.vertices()); }
|
||||
pub fn push_mesh(&mut self, other: &Mesh<V>) { self.verts.extend_from_slice(other.vertices()); }
|
||||
|
||||
/// Map and push the vertices of another mesh onto the end of this mesh.
|
||||
pub fn push_mesh_map<F: FnMut(P::Vertex) -> P::Vertex>(&mut self, other: &Mesh<P>, mut f: F) {
|
||||
pub fn push_mesh_map<F: FnMut(V) -> V>(&mut self, other: &Mesh<V>, mut f: F) {
|
||||
// Reserve enough space in our Vec. This isn't necessary, but it tends to reduce
|
||||
// the number of required (re)allocations.
|
||||
self.verts.reserve(other.vertices().len());
|
||||
@ -86,23 +83,23 @@ impl<P: Pipeline> Mesh<P> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> std::slice::Iter<P::Vertex> { self.verts.iter() }
|
||||
pub fn iter(&self) -> std::slice::Iter<V> { self.verts.iter() }
|
||||
|
||||
/// NOTE: Panics if vertex_range is out of bounds of vertices.
|
||||
pub fn iter_mut(&mut self, vertex_range: Range<usize>) -> std::slice::IterMut<P::Vertex> {
|
||||
pub fn iter_mut(&mut self, vertex_range: Range<usize>) -> std::slice::IterMut<V> {
|
||||
self.verts[vertex_range].iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Pipeline> IntoIterator for Mesh<P> {
|
||||
type IntoIter = std::vec::IntoIter<P::Vertex>;
|
||||
type Item = P::Vertex;
|
||||
impl<V: Vertex> IntoIterator for Mesh<V> {
|
||||
type IntoIter = std::vec::IntoIter<V>;
|
||||
type Item = V;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter { self.verts.into_iter() }
|
||||
}
|
||||
|
||||
impl<P: Pipeline> FromIterator<Tri<P>> for Mesh<P> {
|
||||
fn from_iter<I: IntoIterator<Item = Tri<P>>>(tris: I) -> Self {
|
||||
impl<V: Vertex> FromIterator<Tri<V>> for Mesh<V> {
|
||||
fn from_iter<I: IntoIterator<Item = Tri<V>>>(tris: I) -> Self {
|
||||
tris.into_iter().fold(Self::new(), |mut this, tri| {
|
||||
this.push_tri(tri);
|
||||
this
|
||||
@ -110,8 +107,8 @@ impl<P: Pipeline> FromIterator<Tri<P>> for Mesh<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Pipeline> FromIterator<Quad<P>> for Mesh<P> {
|
||||
fn from_iter<I: IntoIterator<Item = Quad<P>>>(quads: I) -> Self {
|
||||
impl<V: Vertex> FromIterator<Quad<V>> for Mesh<V> {
|
||||
fn from_iter<I: IntoIterator<Item = Quad<V>>>(quads: I) -> Self {
|
||||
quads.into_iter().fold(Self::new(), |mut this, quad| {
|
||||
this.push_quad(quad);
|
||||
this
|
||||
@ -120,33 +117,28 @@ impl<P: Pipeline> FromIterator<Quad<P>> for Mesh<P> {
|
||||
}
|
||||
|
||||
/// Represents a triangle stored on the CPU.
|
||||
pub struct Tri<P: Pipeline> {
|
||||
a: P::Vertex,
|
||||
b: P::Vertex,
|
||||
c: P::Vertex,
|
||||
pub struct Tri<V: Vertex> {
|
||||
a: V,
|
||||
b: V,
|
||||
c: V,
|
||||
}
|
||||
|
||||
impl<P: Pipeline> Tri<P> {
|
||||
pub fn new(a: P::Vertex, b: P::Vertex, c: P::Vertex) -> Self { Self { a, b, c } }
|
||||
impl<V: Vertex> Tri<V> {
|
||||
pub fn new(a: V, b: V, c: V) -> Self { Self { a, b, c } }
|
||||
}
|
||||
|
||||
/// Represents a quad stored on the CPU.
|
||||
pub struct Quad<P: Pipeline> {
|
||||
a: P::Vertex,
|
||||
b: P::Vertex,
|
||||
c: P::Vertex,
|
||||
d: P::Vertex,
|
||||
pub struct Quad<V: Vertex> {
|
||||
a: V,
|
||||
b: V,
|
||||
c: V,
|
||||
d: V,
|
||||
}
|
||||
|
||||
impl<P: Pipeline> Quad<P> {
|
||||
pub fn new(a: P::Vertex, b: P::Vertex, c: P::Vertex, d: P::Vertex) -> Self {
|
||||
Self { a, b, c, d }
|
||||
}
|
||||
impl<V: Vertex> Quad<V> {
|
||||
pub fn new(a: V, b: V, c: V, d: V) -> Self { Self { a, b, c, d } }
|
||||
|
||||
pub fn rotated_by(self, n: usize) -> Self
|
||||
where
|
||||
P::Vertex: Clone,
|
||||
{
|
||||
pub fn rotated_by(self, n: usize) -> Self {
|
||||
let verts = [self.a, self.b, self.c, self.d];
|
||||
|
||||
Self {
|
||||
|
@ -1,3 +1,4 @@
|
||||
mod buffer;
|
||||
#[allow(clippy::single_component_path_imports)] // TODO: Pending review in #587
|
||||
pub mod consts;
|
||||
mod error;
|
||||
@ -44,25 +45,9 @@ pub use self::{
|
||||
},
|
||||
texture::Texture,
|
||||
};
|
||||
pub use gfx::texture::{FilterMethod, WrapMode};
|
||||
pub use wgpu::{AddressMode, FilterMode};
|
||||
|
||||
#[cfg(feature = "gl")]
|
||||
use gfx_device_gl as gfx_backend;
|
||||
|
||||
/// Used to represent a specific rendering configuration.
|
||||
///
|
||||
/// Note that pipelines are tied to the
|
||||
/// rendering backend, and as such it is necessary to modify the rendering
|
||||
/// subsystem when adding new pipelines - custom pipelines are not currently an
|
||||
/// objective of the rendering subsystem.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// - `SkyboxPipeline`
|
||||
/// - `FigurePipeline`
|
||||
pub trait Pipeline {
|
||||
type Vertex: Clone + gfx::traits::Pod + gfx::pso::buffer::Structure<gfx::format::Format>;
|
||||
}
|
||||
trait Vertex = Clone + zerocopy::AsBytes;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
/// Anti-aliasing modes
|
||||
|
@ -1,69 +1,48 @@
|
||||
use super::{gfx_backend, mesh::Mesh, Pipeline, RenderError};
|
||||
use gfx::{
|
||||
buffer::Role,
|
||||
memory::{Bind, Usage},
|
||||
traits::FactoryExt,
|
||||
Factory,
|
||||
};
|
||||
use super::{buffer::Buffer, mesh::Mesh, RenderError, Vertex};
|
||||
use std::ops::Range;
|
||||
|
||||
/// Represents a mesh that has been sent to the GPU.
|
||||
pub struct Model<P: Pipeline> {
|
||||
pub vbuf: gfx::handle::Buffer<gfx_backend::Resources, P::Vertex>,
|
||||
pub struct SubModel<'a, V: Vertex> {
|
||||
pub vertex_range: Range<u32>,
|
||||
buf: &'a wgpu::Buffer,
|
||||
phantom_data: std::marker::PhantomData<V>,
|
||||
}
|
||||
|
||||
impl<P: Pipeline> Model<P> {
|
||||
pub fn new(factory: &mut gfx_backend::Factory, mesh: &Mesh<P>) -> Self {
|
||||
impl<'a, V: Vertex> SubModel<'a, V> {
|
||||
pub fn buf(&self) -> &wgpu::Buffer { self.buf }
|
||||
}
|
||||
|
||||
/// Represents a mesh that has been sent to the GPU.
|
||||
pub struct Model<V: Vertex> {
|
||||
vbuf: Buffer<V>,
|
||||
}
|
||||
|
||||
impl<V: Vertex> Model<V> {
|
||||
pub fn new(device: &wgpu::Device, mesh: &Mesh<V>) -> Self {
|
||||
Self {
|
||||
vbuf: factory.create_vertex_buffer(mesh.vertices()),
|
||||
vertex_range: 0..mesh.vertices().len() as u32,
|
||||
vbuf: Buffer::new_with_data(device, wgpu::BufferUsage::VERTEX, mesh.vertices()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vertex_range(&self) -> Range<u32> { self.vertex_range.clone() }
|
||||
|
||||
/// Create a model with a slice of a portion of this model to send to the
|
||||
/// renderer.
|
||||
pub fn submodel(&self, vertex_range: Range<u32>) -> Model<P> {
|
||||
Model {
|
||||
vbuf: self.vbuf.clone(),
|
||||
vertex_range,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a mesh on the GPU which can be updated dynamically.
|
||||
pub struct DynamicModel<P: Pipeline> {
|
||||
pub vbuf: gfx::handle::Buffer<gfx_backend::Resources, P::Vertex>,
|
||||
}
|
||||
|
||||
impl<P: Pipeline> DynamicModel<P> {
|
||||
pub fn new(factory: &mut gfx_backend::Factory, size: usize) -> Result<Self, RenderError> {
|
||||
Ok(Self {
|
||||
vbuf: factory
|
||||
.create_buffer(size, Role::Vertex, Usage::Dynamic, Bind::empty())
|
||||
.map_err(RenderError::BufferCreationError)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a model with a slice of a portion of this model to send to the
|
||||
/// renderer.
|
||||
pub fn submodel(&self, vertex_range: Range<u32>) -> Model<P> {
|
||||
Model {
|
||||
vbuf: self.vbuf.clone(),
|
||||
pub fn submodel(&self, vertex_range: Range<u32>) -> SubModel<V> {
|
||||
SubModel {
|
||||
vertex_range,
|
||||
buf: self.buf(),
|
||||
phantom_data: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&self,
|
||||
encoder: &mut gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
||||
mesh: &Mesh<P>,
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
mesh: &Mesh<V>,
|
||||
offset: usize,
|
||||
) -> Result<(), RenderError> {
|
||||
encoder
|
||||
.update_buffer(&self.vbuf, mesh.vertices(), offset)
|
||||
.map_err(RenderError::UpdateError)
|
||||
self.buf.update(device, queue, mesh.vertices(), offset)
|
||||
}
|
||||
|
||||
pub fn buf(&self) -> &wgpu::Buffer { self.vbuf.buf }
|
||||
}
|
||||
|
@ -1,56 +1,28 @@
|
||||
use super::{
|
||||
super::{Mesh, Model, Pipeline, TerrainPipeline, TgtColorFmt, TgtDepthStencilFmt},
|
||||
super::{Mesh, Model, TerrainPipeline, TgtColorFmt, TgtDepthStencilFmt},
|
||||
shadow, Globals, Light, Shadow,
|
||||
};
|
||||
use crate::mesh::greedy::GreedyMesh;
|
||||
use gfx::{
|
||||
self, gfx_constant_struct_meta, gfx_defines, gfx_impl_struct_meta, gfx_pipeline,
|
||||
gfx_pipeline_inner, state::ColorMask,
|
||||
};
|
||||
use vek::*;
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
gfx_defines! {
|
||||
constant Locals {
|
||||
model_mat: [[f32; 4]; 4] = "model_mat",
|
||||
highlight_col: [f32; 4] = "highlight_col",
|
||||
model_light: [f32; 4] = "model_light",
|
||||
model_glow: [f32; 4] = "model_glow",
|
||||
atlas_offs: [i32; 4] = "atlas_offs",
|
||||
model_pos: [f32; 3] = "model_pos",
|
||||
flags: u32 = "flags",
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, AsBytes)]
|
||||
pub struct Locals {
|
||||
model_mat: [[f32; 4]; 4],
|
||||
highlight_col: [f32; 4],
|
||||
model_light: [f32; 4],
|
||||
model_glow: [f32; 4],
|
||||
atlas_offs: [i32; 4],
|
||||
model_pos: [f32; 3],
|
||||
flags: u32,
|
||||
}
|
||||
|
||||
constant BoneData {
|
||||
bone_mat: [[f32; 4]; 4] = "bone_mat",
|
||||
normals_mat: [[f32; 4]; 4] = "normals_mat",
|
||||
}
|
||||
|
||||
pipeline pipe {
|
||||
vbuf: gfx::VertexBuffer<<TerrainPipeline as Pipeline>::Vertex> = (),
|
||||
// abuf: gfx::VertexBuffer<<TerrainPipeline as Pipeline>::Vertex> = (),
|
||||
col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light",
|
||||
|
||||
locals: gfx::ConstantBuffer<Locals> = "u_locals",
|
||||
globals: gfx::ConstantBuffer<Globals> = "u_globals",
|
||||
bones: gfx::ConstantBuffer<BoneData> = "u_bones",
|
||||
lights: gfx::ConstantBuffer<Light> = "u_lights",
|
||||
shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
|
||||
|
||||
point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
|
||||
directed_shadow_maps: gfx::TextureSampler<f32> = "t_directed_shadow_maps",
|
||||
|
||||
alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
|
||||
horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
|
||||
|
||||
noise: gfx::TextureSampler<f32> = "t_noise",
|
||||
|
||||
// Shadow stuff
|
||||
light_shadows: gfx::ConstantBuffer<shadow::Locals> = "u_light_shadows",
|
||||
|
||||
tgt_color: gfx::BlendTarget<TgtColorFmt> = ("tgt_color", ColorMask::all(), gfx::preset::blend::ALPHA),
|
||||
tgt_depth_stencil: gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
|
||||
// tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> = (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,(StencilOp::Keep,StencilOp::Keep,StencilOp::Replace))),
|
||||
}
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, AsBytes)]
|
||||
pub struct BoneData {
|
||||
bone_mat: [[f32; 4]; 4],
|
||||
normals_mat: [[f32; 4]; 4],
|
||||
}
|
||||
|
||||
impl Locals {
|
||||
@ -76,6 +48,21 @@ impl Locals {
|
||||
flags,
|
||||
}
|
||||
}
|
||||
|
||||
fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Locals {
|
||||
@ -99,16 +86,39 @@ impl BoneData {
|
||||
normals_mat: normals_mat.into_col_arrays(),
|
||||
}
|
||||
}
|
||||
|
||||
fn layout(device: &wgpu::Device) -> wgpu::BindGroupLayout {
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
|
||||
ty: wgpu::BindingType::UniformBuffer {
|
||||
dynamic: false,
|
||||
min_binding_size: None,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BoneData {
|
||||
fn default() -> Self { Self::new(anim::vek::Mat4::identity(), anim::vek::Mat4::identity()) }
|
||||
}
|
||||
|
||||
pub struct FigurePipeline;
|
||||
pub struct FigureLayout {
|
||||
pub locals: wgpu::BindGroupLayout,
|
||||
pub bone_data: wgpu::BindGroupLayout,
|
||||
}
|
||||
|
||||
impl Pipeline for FigurePipeline {
|
||||
type Vertex = <TerrainPipeline as Pipeline>::Vertex;
|
||||
impl FigureLayout {
|
||||
pub fn new(device: &wgpu::Device) -> Self {
|
||||
Self {
|
||||
locals: Locals::locals_layout(device),
|
||||
bone_data: BoneData::bone_data_layout(device),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FigureModel {
|
||||
@ -130,3 +140,49 @@ impl FigureModel {
|
||||
}
|
||||
|
||||
pub type BoneMeshes = (Mesh<TerrainPipeline>, anim::vek::Aabb<f32>);
|
||||
|
||||
//gfx_defines! {
|
||||
// constant Locals {
|
||||
// model_mat: [[f32; 4]; 4] = "model_mat",
|
||||
// highlight_col: [f32; 4] = "highlight_col",
|
||||
// model_light: [f32; 4] = "model_light",
|
||||
// atlas_offs: [i32; 4] = "atlas_offs",
|
||||
// model_pos: [f32; 3] = "model_pos",
|
||||
// flags: u32 = "flags",
|
||||
// }
|
||||
//
|
||||
// constant BoneData {
|
||||
// bone_mat: [[f32; 4]; 4] = "bone_mat",
|
||||
// normals_mat: [[f32; 4]; 4] = "normals_mat",
|
||||
// }
|
||||
//
|
||||
// pipeline pipe {
|
||||
// vbuf: gfx::VertexBuffer<<TerrainPipeline as Pipeline>::Vertex> = (),
|
||||
// // abuf: gfx::VertexBuffer<<TerrainPipeline as Pipeline>::Vertex> =
|
||||
// (), col_lights: gfx::TextureSampler<[f32; 4]> = "t_col_light",
|
||||
//
|
||||
// locals: gfx::ConstantBuffer<Locals> = "u_locals",
|
||||
// globals: gfx::ConstantBuffer<Globals> = "u_globals",
|
||||
// bones: gfx::ConstantBuffer<BoneData> = "u_bones",
|
||||
// lights: gfx::ConstantBuffer<Light> = "u_lights",
|
||||
// shadows: gfx::ConstantBuffer<Shadow> = "u_shadows",
|
||||
//
|
||||
// point_shadow_maps: gfx::TextureSampler<f32> = "t_point_shadow_maps",
|
||||
// directed_shadow_maps: gfx::TextureSampler<f32> =
|
||||
// "t_directed_shadow_maps",
|
||||
//
|
||||
// alt: gfx::TextureSampler<[f32; 2]> = "t_alt",
|
||||
// horizon: gfx::TextureSampler<[f32; 4]> = "t_horizon",
|
||||
//
|
||||
// noise: gfx::TextureSampler<f32> = "t_noise",
|
||||
//
|
||||
// // Shadow stuff
|
||||
// light_shadows: gfx::ConstantBuffer<shadow::Locals> =
|
||||
// "u_light_shadows",
|
||||
//
|
||||
// tgt_color: gfx::BlendTarget<TgtColorFmt> = ("tgt_color",
|
||||
// ColorMask::all(), gfx::preset::blend::ALPHA), tgt_depth_stencil:
|
||||
// gfx::DepthTarget<TgtDepthStencilFmt> = gfx::preset::depth::LESS_EQUAL_WRITE,
|
||||
// // tgt_depth_stencil: gfx::DepthStencilTarget<TgtDepthStencilFmt> =
|
||||
// (gfx::preset::depth::LESS_EQUAL_WRITE,Stencil::new(Comparison::Always,0xff,
|
||||
// (StencilOp::Keep,StencilOp::Keep,StencilOp::Replace))), }
|
||||
|
@ -1,28 +1,21 @@
|
||||
use super::{
|
||||
consts::Consts,
|
||||
gfx_backend,
|
||||
instances::Instances,
|
||||
mesh::Mesh,
|
||||
model::{DynamicModel, Model},
|
||||
model::{Model},
|
||||
pipelines::{
|
||||
clouds, figure, fluid, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain,
|
||||
ui, GlobalModel, Globals,
|
||||
},
|
||||
texture::Texture,
|
||||
AaMode, CloudMode, FilterMethod, FluidMode, LightingMode, Pipeline, RenderError, RenderMode,
|
||||
ShadowMapMode, ShadowMode, WrapMode,
|
||||
AaMode, CloudMode, FilterMode, FluidMode, LightingMode, RenderError, RenderMode,
|
||||
ShadowMapMode, ShadowMode, AddressMode,
|
||||
};
|
||||
use common::assets::{self, AssetExt, AssetHandle};
|
||||
use common_base::span;
|
||||
use core::convert::TryFrom;
|
||||
use gfx::{
|
||||
self,
|
||||
handle::Sampler,
|
||||
state::Comparison,
|
||||
traits::{Device, Factory, FactoryExt},
|
||||
};
|
||||
use glsl_include::Context as IncludeContext;
|
||||
use tracing::{error, warn};
|
||||
use tracing::{error, info, warn};
|
||||
use vek::*;
|
||||
|
||||
/// Represents the format of the pre-processed color target.
|
||||
@ -225,13 +218,11 @@ impl assets::Compound for Shaders {
|
||||
pub struct ShadowMapRenderer {
|
||||
// directed_encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
||||
// point_encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
||||
directed_depth_stencil_view: ShadowDepthStencilView,
|
||||
directed_res: ShadowResourceView,
|
||||
directed_sampler: Sampler<gfx_backend::Resources>,
|
||||
directed_depth_stencil_view: wgpu::TextureView,
|
||||
directed_sampler: wgpu::Sampler,
|
||||
|
||||
point_depth_stencil_view: ShadowDepthStencilView,
|
||||
point_res: ShadowResourceView,
|
||||
point_sampler: Sampler<gfx_backend::Resources>,
|
||||
point_depth_stencil_view: wgpu::TextureView,
|
||||
point_sampler: wgpu::Sampler,
|
||||
|
||||
point_pipeline: GfxPipeline<shadow::pipe::Init<'static>>,
|
||||
terrain_directed_pipeline: GfxPipeline<shadow::pipe::Init<'static>>,
|
||||
@ -243,22 +234,18 @@ pub struct ShadowMapRenderer {
|
||||
/// GPU, along with pipeline state objects (PSOs) needed to renderer different
|
||||
/// kinds of models to the screen.
|
||||
pub struct Renderer {
|
||||
device: gfx_backend::Device,
|
||||
encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
||||
factory: gfx_backend::Factory,
|
||||
device: wgpu::Device,
|
||||
queue: wgpu::Queue,
|
||||
swap_chain: wgpu::SwapChain,
|
||||
|
||||
win_color_view: WinColorView,
|
||||
win_depth_view: WinDepthView,
|
||||
win_depth_view: wgpu::TextureView,
|
||||
|
||||
tgt_color_view: TgtColorView,
|
||||
tgt_depth_stencil_view: TgtDepthStencilView,
|
||||
tgt_color_view_pp: TgtColorView,
|
||||
tgt_color_view: wgpu::TextureView,
|
||||
tgt_depth_stencil_view: wgpu::TextureView,
|
||||
// TODO: rename
|
||||
tgt_color_pp_view: wgpu::TextureView,
|
||||
|
||||
tgt_color_res: TgtColorRes,
|
||||
tgt_depth_res: TgtDepthRes,
|
||||
tgt_color_res_pp: TgtColorRes,
|
||||
|
||||
sampler: Sampler<gfx_backend::Resources>,
|
||||
sampler: wgpu::Sampler,
|
||||
|
||||
shadow_map: Option<ShadowMapRenderer>,
|
||||
|
||||
@ -285,11 +272,8 @@ pub struct Renderer {
|
||||
impl Renderer {
|
||||
/// Create a new `Renderer` from a variety of backend-specific components
|
||||
/// and the window targets.
|
||||
pub fn new(
|
||||
mut device: gfx_backend::Device,
|
||||
mut factory: gfx_backend::Factory,
|
||||
win_color_view: WinColorView,
|
||||
win_depth_view: WinDepthView,
|
||||
pub async fn new(
|
||||
window: &winit::window::Window,
|
||||
mode: RenderMode,
|
||||
) -> Result<Self, RenderError> {
|
||||
// Enable seamless cubemaps globally, where available--they are essentially a
|
||||
@ -297,12 +281,59 @@ impl Renderer {
|
||||
//
|
||||
// Note that since we only have to enable this once globally, there is no point
|
||||
// in doing this on rerender.
|
||||
Self::enable_seamless_cube_maps(&mut device);
|
||||
// Self::enable_seamless_cube_maps(&mut device);
|
||||
|
||||
let dims = win_color_view.get_dimensions();
|
||||
let dims = window.inner_size();
|
||||
|
||||
let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY | wgpu::BackendBit::SECONDARY);
|
||||
|
||||
// This is unsafe because the window handle must be valid, if you find a way to
|
||||
// have an invalid winit::Window then you have bigger issues
|
||||
#[allow(unsafe_code)]
|
||||
let surface = unsafe { instance.create_surface(window) };
|
||||
|
||||
let adapter = instance
|
||||
.request_adapter(wgpu::RequestAdapterOptionsBase {
|
||||
power_preference: wgpu::PowerPreference::HighPerformance,
|
||||
compatible_surface: Some(surface),
|
||||
})
|
||||
.await
|
||||
.ok_or(RenderError::CouldNotFindAdapter)?;
|
||||
|
||||
use wgpu::{Features, Limits};
|
||||
|
||||
let (device, queue) = adapter
|
||||
.request_device(
|
||||
wgpu::DeviceDescriptor {
|
||||
// TODO
|
||||
features: Features::DEPTH_CLAMPING,
|
||||
limits: Limits::default(),
|
||||
shader_validation: true,
|
||||
},
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let info = device.get_info();
|
||||
info!(
|
||||
?info.name,
|
||||
?info.vendor,
|
||||
?info.backend,
|
||||
?info.device,
|
||||
?info.device_type,
|
||||
"selected graphics device"
|
||||
);
|
||||
|
||||
let swap_chain = device.create_swap_chain(&surface, &wgpu::SwapChainDescriptor {
|
||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||
width: dims.0,
|
||||
height: dims.1,
|
||||
present_mode: wgpu::PresentMode::Immediate,
|
||||
});
|
||||
|
||||
let shadow_views = Self::create_shadow_views(
|
||||
&mut factory,
|
||||
&device,
|
||||
(dims.0, dims.1),
|
||||
&ShadowMapMode::try_from(mode.shadow).unwrap_or_default(),
|
||||
)
|
||||
@ -328,16 +359,18 @@ impl Renderer {
|
||||
point_shadow_pipeline,
|
||||
terrain_directed_shadow_pipeline,
|
||||
figure_directed_shadow_pipeline,
|
||||
) = create_pipelines(&mut factory, &shaders.read(), &mode, shadow_views.is_some())?;
|
||||
) = create_pipelines(
|
||||
&device,
|
||||
&mode,
|
||||
shadow_views.is_some(),
|
||||
)?;
|
||||
|
||||
let (
|
||||
tgt_color_view,
|
||||
tgt_depth_stencil_view,
|
||||
tgt_color_view_pp,
|
||||
tgt_color_res,
|
||||
tgt_depth_res,
|
||||
tgt_color_res_pp,
|
||||
) = Self::create_rt_views(&mut factory, (dims.0, dims.1), &mode)?;
|
||||
tgt_color_pp_view,
|
||||
win_depth_view,
|
||||
) = Self::create_rt_views(&device, (dims.0, dims.1), &mode)?;
|
||||
|
||||
let shadow_map = if let (
|
||||
Some(point_pipeline),
|
||||
@ -360,13 +393,11 @@ impl Renderer {
|
||||
) = shadow_views;
|
||||
Some(ShadowMapRenderer {
|
||||
directed_depth_stencil_view,
|
||||
directed_res,
|
||||
directed_sampler,
|
||||
|
||||
// point_encoder: factory.create_command_buffer().into(),
|
||||
// directed_encoder: factory.create_command_buffer().into(),
|
||||
point_depth_stencil_view,
|
||||
point_res,
|
||||
point_sampler,
|
||||
|
||||
point_pipeline,
|
||||
@ -377,34 +408,36 @@ impl Renderer {
|
||||
None
|
||||
};
|
||||
|
||||
let sampler = factory.create_sampler(gfx::texture::SamplerInfo::new(
|
||||
gfx::texture::FilterMethod::Bilinear,
|
||||
gfx::texture::WrapMode::Clamp,
|
||||
));
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
label: None,
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter: wgpu::FilterMode::Linear,
|
||||
min_filter: wgpu::FilterMode::Linear,
|
||||
mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
compare: None,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
let noise_tex = Texture::new(
|
||||
&mut factory,
|
||||
&device,
|
||||
&queue,
|
||||
&assets::Image::load_expect("voxygen.texture.noise").read().0,
|
||||
Some(gfx::texture::FilterMethod::Trilinear),
|
||||
Some(gfx::texture::WrapMode::Tile),
|
||||
None,
|
||||
Some(wgpu::FilterMode::Linear),
|
||||
Some(wgpu::AddressMode::Repeat),
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
device,
|
||||
encoder: factory.create_command_buffer().into(),
|
||||
factory,
|
||||
queue,
|
||||
swap_chain,
|
||||
|
||||
win_color_view,
|
||||
win_depth_view,
|
||||
|
||||
tgt_color_view,
|
||||
tgt_depth_stencil_view,
|
||||
tgt_color_view_pp,
|
||||
|
||||
tgt_color_res,
|
||||
tgt_depth_res,
|
||||
tgt_color_res_pp,
|
||||
tgt_color_pp_view,
|
||||
|
||||
sampler,
|
||||
|
||||
@ -483,7 +516,7 @@ impl Renderer {
|
||||
let (
|
||||
tgt_color_view,
|
||||
tgt_depth_stencil_view,
|
||||
tgt_color_view_pp,
|
||||
tgt_color_pp_view,
|
||||
tgt_color_res,
|
||||
tgt_depth_res,
|
||||
tgt_color_res_pp,
|
||||
@ -493,7 +526,7 @@ impl Renderer {
|
||||
self.tgt_color_res_pp = tgt_color_res_pp;
|
||||
self.tgt_color_view = tgt_color_view;
|
||||
self.tgt_depth_stencil_view = tgt_depth_stencil_view;
|
||||
self.tgt_color_view_pp = tgt_color_view_pp;
|
||||
self.tgt_color_pp_view = tgt_color_pp_view;
|
||||
if let (Some(shadow_map), ShadowMode::Map(mode)) =
|
||||
(self.shadow_map.as_mut(), self.mode.shadow)
|
||||
{
|
||||
@ -525,90 +558,103 @@ impl Renderer {
|
||||
}
|
||||
|
||||
fn create_rt_views(
|
||||
factory: &mut gfx_device_gl::Factory,
|
||||
device: &wgpu::Device,
|
||||
size: (u16, u16),
|
||||
mode: &RenderMode,
|
||||
) -> Result<
|
||||
(
|
||||
TgtColorView,
|
||||
TgtDepthStencilView,
|
||||
TgtColorView,
|
||||
TgtColorRes,
|
||||
TgtDepthRes,
|
||||
TgtColorRes,
|
||||
),
|
||||
RenderError,
|
||||
> {
|
||||
) -> Result<(wgpu::TextureView, wgpu::TextureView, wgpu::TextureView, wgpu::TextureView), RenderError> {
|
||||
let upscaled = Vec2::from(size)
|
||||
.map(|e: u16| (e as f32 * mode.upscale_mode.factor) as u16)
|
||||
.into_tuple();
|
||||
let kind = match mode.aa {
|
||||
AaMode::None | AaMode::Fxaa => {
|
||||
gfx::texture::Kind::D2(upscaled.0, upscaled.1, gfx::texture::AaMode::Single)
|
||||
},
|
||||
let (width, height, sample_count) = match mode.aa {
|
||||
AaMode::None | AaMode::Fxaa => (upscaled.0, upscaled.1, 1),
|
||||
// TODO: Ensure sampling in the shader is exactly between the 4 texels
|
||||
AaMode::MsaaX4 => {
|
||||
gfx::texture::Kind::D2(upscaled.0, upscaled.1, gfx::texture::AaMode::Multi(4))
|
||||
},
|
||||
AaMode::MsaaX8 => {
|
||||
gfx::texture::Kind::D2(upscaled.0, upscaled.1, gfx::texture::AaMode::Multi(8))
|
||||
},
|
||||
AaMode::MsaaX16 => {
|
||||
gfx::texture::Kind::D2(upscaled.0, upscaled.1, gfx::texture::AaMode::Multi(16))
|
||||
},
|
||||
// TODO: Figure out how to do upscaling correctly with SSAA
|
||||
AaMode::MsaaX4 => (upscaled.0, upscaled.1, 4),
|
||||
AaMode::MsaaX8 => (upscaled.0, upscaled.1, 8),
|
||||
AaMode::MsaaX16 => (upscaled.0, upscaled.1, 16),
|
||||
};
|
||||
let levels = 1;
|
||||
|
||||
let color_cty = <<TgtColorFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped
|
||||
>::get_channel_type();
|
||||
let mut color_tex = || {
|
||||
factory.create_texture(
|
||||
kind,
|
||||
levels,
|
||||
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::RENDER_TARGET,
|
||||
gfx::memory::Usage::Data,
|
||||
Some(color_cty),
|
||||
)
|
||||
};
|
||||
let tgt_color_tex = color_tex()?;
|
||||
let tgt_color_tex_pp = color_tex()?;
|
||||
let mut color_res = |tex| {
|
||||
factory.view_texture_as_shader_resource::<TgtColorFmt>(
|
||||
tex,
|
||||
(0, levels - 1),
|
||||
gfx::format::Swizzle::new(),
|
||||
)
|
||||
};
|
||||
let tgt_color_res = color_res(&tgt_color_tex)?;
|
||||
let tgt_color_res_pp = color_res(&tgt_color_tex_pp)?;
|
||||
let tgt_color_view = factory.view_texture_as_render_target(&tgt_color_tex, 0, None)?;
|
||||
let tgt_color_view_pp =
|
||||
factory.view_texture_as_render_target(&tgt_color_tex_pp, 0, None)?;
|
||||
let mut color_view = || {
|
||||
let tex = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size: wgpu::Extent3d {
|
||||
width,
|
||||
height,
|
||||
depth: 1,
|
||||
},
|
||||
mip_level_count: levels,
|
||||
sample_count,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
});
|
||||
|
||||
let depth_stencil_cty = <<TgtDepthStencilFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type();
|
||||
let tgt_depth_stencil_tex = factory.create_texture(
|
||||
kind,
|
||||
levels,
|
||||
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL,
|
||||
gfx::memory::Usage::Data,
|
||||
Some(depth_stencil_cty),
|
||||
)?;
|
||||
let tgt_depth_res = factory.view_texture_as_shader_resource::<TgtDepthStencilFmt>(
|
||||
&tgt_depth_stencil_tex,
|
||||
(0, levels - 1),
|
||||
gfx::format::Swizzle::new(),
|
||||
)?;
|
||||
tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
label: None,
|
||||
format: Some(wgpu::TextureFormat::Rgba8UnormSrgb),
|
||||
dimension: Some(wgpu::TextureViewDimension::D2),
|
||||
aspect: wgpu::TextureAspect::Color,
|
||||
base_mip_level: 0,
|
||||
level_count: Some(levels),
|
||||
base_array_layer: 0,
|
||||
array_layer_count: None,
|
||||
})
|
||||
};
|
||||
|
||||
let tgt_color_view = color_view();
|
||||
let tgt_color_pp_view = color_view();
|
||||
|
||||
let tgt_depth_stencil_tex = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size: wgpu::Extent3d {
|
||||
width,
|
||||
height,
|
||||
depth: 1,
|
||||
},
|
||||
mip_level_count: levels,
|
||||
sample_count,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Depth24Plus,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
});
|
||||
let tgt_depth_stencil_view =
|
||||
factory.view_texture_as_depth_stencil_trivial(&tgt_depth_stencil_tex)?;
|
||||
tgt_depth_stencil_tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
label: None,
|
||||
format: Some(wgpu::TextureFormat::Depth24Plus),
|
||||
dimension: Some(wgpu::TextureViewDimension::D2),
|
||||
aspect: wgpu::TextureAspect::DepthOnly,
|
||||
base_mip_level: 0,
|
||||
level_count: Some(levels),
|
||||
base_array_layer: 0,
|
||||
array_layer_count: None,
|
||||
});
|
||||
|
||||
Ok((
|
||||
tgt_color_view,
|
||||
tgt_depth_stencil_view,
|
||||
tgt_color_view_pp,
|
||||
tgt_color_res,
|
||||
tgt_depth_res,
|
||||
tgt_color_res_pp,
|
||||
))
|
||||
let win_depth_tex = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size: wgpu::Extent3d {
|
||||
width: size.0,
|
||||
height: size.1,
|
||||
depth: 1,
|
||||
},
|
||||
mip_level_count: levels,
|
||||
sample_count,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Depth24Plus,
|
||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
});
|
||||
let win_depth_view = tgt_depth_stencil_tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
label: None,
|
||||
format: Some(wgpu::TextureFormat::Depth24Plus),
|
||||
dimension: Some(wgpu::TextureViewDimension::D2),
|
||||
aspect: wgpu::TextureAspect::DepthOnly,
|
||||
base_mip_level: 0,
|
||||
level_count: Some(levels),
|
||||
base_array_layer: 0,
|
||||
array_layer_count: None,
|
||||
});
|
||||
|
||||
Ok((tgt_color_view, tgt_depth_stencil_view, tgt_color_pp_view, win_depth_view))
|
||||
}
|
||||
|
||||
/// Create textures and views for shadow maps.
|
||||
@ -616,24 +662,24 @@ impl Renderer {
|
||||
// disable the type complexity lint.
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn create_shadow_views(
|
||||
factory: &mut gfx_device_gl::Factory,
|
||||
device: &wgpu::Device,
|
||||
size: (u16, u16),
|
||||
mode: &ShadowMapMode,
|
||||
) -> Result<
|
||||
(
|
||||
ShadowDepthStencilView,
|
||||
ShadowResourceView,
|
||||
Sampler<gfx_backend::Resources>,
|
||||
ShadowDepthStencilView,
|
||||
ShadowResourceView,
|
||||
Sampler<gfx_backend::Resources>,
|
||||
wgpu::TextureView,
|
||||
wgpu::Sampler,
|
||||
wgpu::TextureView,
|
||||
wgpu::Sampler,
|
||||
),
|
||||
RenderError,
|
||||
> {
|
||||
// (Attempt to) apply resolution factor to shadow map resolution.
|
||||
let resolution_factor = mode.resolution.clamped(0.25, 4.0);
|
||||
|
||||
let max_texture_size = Self::max_texture_size_raw(factory);
|
||||
// This value is temporary as there are plans to include a way to get this in
|
||||
// wgpu this is just a sane standard for now
|
||||
let max_texture_size = 8000;
|
||||
// Limit to max texture size, rather than erroring.
|
||||
let size = Vec2::new(size.0, size.1).map(|e| {
|
||||
let size = f32::from(e) * resolution_factor;
|
||||
@ -677,72 +723,76 @@ impl Renderer {
|
||||
.filter(|&e| e <= max_texture_size)
|
||||
// Limit to max texture resolution rather than error.
|
||||
.unwrap_or(max_texture_size);
|
||||
let depth_stencil_cty = <<ShadowDepthStencilFmt as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type();
|
||||
|
||||
let point_shadow_tex = factory
|
||||
.create_texture(
|
||||
gfx::texture::Kind::Cube(diag_two_size / 4),
|
||||
levels as gfx::texture::Level,
|
||||
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL,
|
||||
gfx::memory::Usage::Data,
|
||||
Some(depth_stencil_cty),
|
||||
)
|
||||
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?;
|
||||
let point_shadow_tex = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size: wgpu::Extent3d {
|
||||
width: diag_two_size / 4,
|
||||
height: diag_two_size / 4,
|
||||
depth: 6,
|
||||
},
|
||||
mip_level_count: levels,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Depth24Plus,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
});
|
||||
|
||||
let point_tgt_shadow_view = factory
|
||||
.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
|
||||
&point_shadow_tex,
|
||||
0,
|
||||
None,
|
||||
gfx::texture::DepthStencilFlags::empty(),
|
||||
)?;
|
||||
let point_tgt_shadow_view = point_shadow_tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
label: None,
|
||||
format: Some(wgpu::TextureFormat::Depth24Plus),
|
||||
dimension: Some(wgpu::TextureViewDimension::Cube),
|
||||
aspect: wgpu::TextureAspect::DepthOnly,
|
||||
base_mip_level: 0,
|
||||
level_count: Some(levels),
|
||||
base_array_layer: 0,
|
||||
array_layer_count: None,
|
||||
});
|
||||
|
||||
let point_tgt_shadow_res = factory
|
||||
.view_texture_as_shader_resource::<ShadowDepthStencilFmt>(
|
||||
&point_shadow_tex,
|
||||
(0, levels - 1),
|
||||
gfx::format::Swizzle::new(),
|
||||
)?;
|
||||
let directed_shadow_tex = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size: wgpu::Extent3d {
|
||||
width: diag_two_size,
|
||||
height: diag_two_size,
|
||||
depth: 1,
|
||||
},
|
||||
mip_level_count: levels,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Depth24Plus,
|
||||
usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||
});
|
||||
|
||||
let directed_shadow_tex = factory
|
||||
.create_texture(
|
||||
gfx::texture::Kind::D2(diag_two_size, diag_two_size, gfx::texture::AaMode::Single),
|
||||
levels as gfx::texture::Level,
|
||||
gfx::memory::Bind::SHADER_RESOURCE | gfx::memory::Bind::DEPTH_STENCIL,
|
||||
gfx::memory::Usage::Data,
|
||||
Some(depth_stencil_cty),
|
||||
)
|
||||
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?;
|
||||
let directed_tgt_shadow_view = factory
|
||||
.view_texture_as_depth_stencil::<ShadowDepthStencilFmt>(
|
||||
&directed_shadow_tex,
|
||||
0,
|
||||
None,
|
||||
gfx::texture::DepthStencilFlags::empty(),
|
||||
)?;
|
||||
let directed_tgt_shadow_res = factory
|
||||
.view_texture_as_shader_resource::<ShadowDepthStencilFmt>(
|
||||
&directed_shadow_tex,
|
||||
(0, levels - 1),
|
||||
gfx::format::Swizzle::new(),
|
||||
)?;
|
||||
let directed_tgt_shadow_view = point_shadow_tex.create_view(&wgpu::TextureViewDescriptor {
|
||||
label: None,
|
||||
format: Some(wgpu::TextureFormat::Depth24Plus),
|
||||
dimension: Some(wgpu::TextureViewDimension::D2),
|
||||
aspect: wgpu::TextureAspect::DepthOnly,
|
||||
base_mip_level: 0,
|
||||
level_count: Some(levels),
|
||||
base_array_layer: 0,
|
||||
array_layer_count: None,
|
||||
});
|
||||
|
||||
let mut sampler_info = gfx::texture::SamplerInfo::new(
|
||||
gfx::texture::FilterMethod::Bilinear,
|
||||
// Lights should always be assumed to flood areas we can't see.
|
||||
gfx::texture::WrapMode::Border,
|
||||
);
|
||||
sampler_info.comparison = Some(Comparison::LessEqual);
|
||||
sampler_info.border = [1.0; 4].into();
|
||||
let point_shadow_tex_sampler = factory.create_sampler(sampler_info);
|
||||
let directed_shadow_tex_sampler = factory.create_sampler(sampler_info);
|
||||
let sampler_info = wgpu::SamplerDescriptor {
|
||||
label: None,
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter: wgpu::FilterMode::Linear,
|
||||
min_filter: wgpu::FilterMode::Linear,
|
||||
mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
compare: Some(wgpu::CompareFunction::LessEqual),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let point_shadow_tex_sampler = device.create_sampler(&sampler_info);
|
||||
let directed_shadow_tex_sampler = device.create_sampler(&sampler_info);
|
||||
|
||||
Ok((
|
||||
point_tgt_shadow_view,
|
||||
point_tgt_shadow_res,
|
||||
point_shadow_tex_sampler,
|
||||
directed_tgt_shadow_view,
|
||||
directed_tgt_shadow_res,
|
||||
directed_shadow_tex_sampler,
|
||||
))
|
||||
}
|
||||
@ -797,51 +847,22 @@ impl Renderer {
|
||||
/// available.
|
||||
#[allow(unsafe_code)]
|
||||
fn enable_seamless_cube_maps(device: &mut gfx_backend::Device) {
|
||||
unsafe {
|
||||
// NOTE: Currently just fail silently rather than complain if the computer is on
|
||||
// a version lower than 3.2, where seamless cubemaps were introduced.
|
||||
if !device.get_info().is_version_supported(3, 2) {
|
||||
return;
|
||||
}
|
||||
todo!()
|
||||
// unsafe {
|
||||
// // NOTE: Currently just fail silently rather than complain if the
|
||||
// computer is on // a version lower than 3.2, where
|
||||
// seamless cubemaps were introduced. if !device.get_info().
|
||||
// is_version_supported(3, 2) { return;
|
||||
// }
|
||||
|
||||
// NOTE: Safe because GL_TEXTURE_CUBE_MAP_SEAMLESS is supported by OpenGL 3.2+
|
||||
// (see https://www.khronos.org/opengl/wiki/Cubemap_Texture#Seamless_cubemap);
|
||||
// enabling seamless cube maps should always be safe regardless of the state of
|
||||
// the OpenGL context, so no further checks are needed.
|
||||
device.with_gl(|gl| {
|
||||
gl.Enable(gfx_gl::TEXTURE_CUBE_MAP_SEAMLESS);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// NOTE: Supported by all but a handful of mobile GPUs
|
||||
/// (see https://github.com/gpuweb/gpuweb/issues/480)
|
||||
/// so wgpu should support it too.
|
||||
#[allow(unsafe_code)]
|
||||
fn set_depth_clamp(device: &mut gfx_backend::Device, depth_clamp: bool) {
|
||||
unsafe {
|
||||
// NOTE: Currently just fail silently rather than complain if the computer is on
|
||||
// a version lower than 3.3, though we probably will complain
|
||||
// elsewhere regardless, since shadow mapping is an optional feature
|
||||
// and having depth clamping disabled won't cause undefined
|
||||
// behavior, just incorrect shadowing from objects behind the viewer.
|
||||
if !device.get_info().is_version_supported(3, 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: Safe because glDepthClamp is (I believe) supported by
|
||||
// OpenGL 3.3, so we shouldn't have to check for other OpenGL versions which
|
||||
// may use different extensions. Also, enabling depth clamping should
|
||||
// essentially always be safe regardless of the state of the OpenGL
|
||||
// context, so no further checks are needed.
|
||||
device.with_gl(|gl| {
|
||||
if depth_clamp {
|
||||
gl.Enable(gfx_gl::DEPTH_CLAMP);
|
||||
} else {
|
||||
gl.Disable(gfx_gl::DEPTH_CLAMP);
|
||||
}
|
||||
});
|
||||
}
|
||||
// // NOTE: Safe because GL_TEXTURE_CUBE_MAP_SEAMLESS is supported
|
||||
// by OpenGL 3.2+ // (see https://www.khronos.org/opengl/wiki/Cubemap_Texture#Seamless_cubemap);
|
||||
// // enabling seamless cube maps should always be safe regardless
|
||||
// of the state of // the OpenGL context, so no further
|
||||
// checks are needed. device.with_gl(|gl| {
|
||||
// gl.Enable(gfx_gl::TEXTURE_CUBE_MAP_SEAMLESS);
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
/// Queue the clearing of the depth target ready for a new frame to be
|
||||
@ -1109,47 +1130,58 @@ impl Renderer {
|
||||
/// a image::DynamicImage.
|
||||
#[allow(clippy::map_clone)] // TODO: Pending review in #587
|
||||
pub fn create_screenshot(&mut self) -> Result<image::DynamicImage, RenderError> {
|
||||
let (width, height) = self.get_resolution().into_tuple();
|
||||
use gfx::{
|
||||
format::{Formatted, SurfaceTyped},
|
||||
memory::Typed,
|
||||
};
|
||||
type WinSurfaceData = <<WinColorFmt as Formatted>::Surface as SurfaceTyped>::DataType;
|
||||
let download = self
|
||||
.factory
|
||||
.create_download_buffer::<WinSurfaceData>(width as usize * height as usize)?;
|
||||
self.encoder.copy_texture_to_buffer_raw(
|
||||
self.win_color_view.raw().get_texture(),
|
||||
None,
|
||||
gfx::texture::RawImageInfo {
|
||||
xoffset: 0,
|
||||
yoffset: 0,
|
||||
zoffset: 0,
|
||||
width,
|
||||
height,
|
||||
depth: 0,
|
||||
format: WinColorFmt::get_format(),
|
||||
mipmap: 0,
|
||||
},
|
||||
download.raw(),
|
||||
0,
|
||||
)?;
|
||||
self.flush();
|
||||
todo!()
|
||||
// let (width, height) = self.get_resolution().into_tuple();
|
||||
|
||||
// Assumes that the format is Rgba8.
|
||||
let raw_data = self
|
||||
.factory
|
||||
.read_mapping(&download)?
|
||||
.chunks_exact(width as usize)
|
||||
.rev()
|
||||
.flatten()
|
||||
.flatten()
|
||||
.map(|&e| e)
|
||||
.collect::<Vec<_>>();
|
||||
Ok(image::DynamicImage::ImageRgba8(
|
||||
// Should not fail if the dimensions are correct.
|
||||
image::ImageBuffer::from_raw(width as u32, height as u32, raw_data).unwrap(),
|
||||
))
|
||||
// let download_buf = self
|
||||
// .device
|
||||
// .create_buffer(&wgpu::BufferDescriptor {
|
||||
// label: None,
|
||||
// size: width * height * 4,
|
||||
// usage : wgpu::BufferUsage::COPY_DST,
|
||||
// mapped_at_creation: true
|
||||
// });
|
||||
|
||||
// let encoder =
|
||||
// self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor
|
||||
// {label: None});
|
||||
|
||||
// encoder.copy_texture_to_buffer(&wgpu::TextureCopyViewBase {
|
||||
// origin: &self.wi
|
||||
// }, destination, copy_size)
|
||||
|
||||
// self.encoder.copy_texture_to_buffer_raw(
|
||||
// self.win_color_view.raw().get_texture(),
|
||||
// None,
|
||||
// gfx::texture::RawImageInfo {
|
||||
// xoffset: 0,
|
||||
// yoffset: 0,
|
||||
// zoffset: 0,
|
||||
// width,
|
||||
// height,
|
||||
// depth: 0,
|
||||
// format: WinColorFmt::get_format(),
|
||||
// mipmap: 0,
|
||||
// },
|
||||
// download.raw(),
|
||||
// 0,
|
||||
// )?;
|
||||
// self.flush();
|
||||
|
||||
// // Assumes that the format is Rgba8.
|
||||
// let raw_data = self
|
||||
// .factory
|
||||
// .read_mapping(&download)?
|
||||
// .chunks_exact(width as usize)
|
||||
// .rev()
|
||||
// .flatten()
|
||||
// .flatten()
|
||||
// .map(|&e| e)
|
||||
// .collect::<Vec<_>>();
|
||||
// Ok(image::DynamicImage::ImageRgba8(
|
||||
// // Should not fail if the dimensions are correct.
|
||||
// image::ImageBuffer::from_raw(width as u32, height as u32,
|
||||
// raw_data).unwrap(), ))
|
||||
}
|
||||
|
||||
/// Queue the rendering of the provided skybox model in the upcoming frame.
|
||||
@ -1825,7 +1857,7 @@ impl Renderer {
|
||||
color_sampler: (self.tgt_color_res.clone(), self.sampler.clone()),
|
||||
depth_sampler: (self.tgt_depth_res.clone(), self.sampler.clone()),
|
||||
noise: (self.noise_tex.srv.clone(), self.noise_tex.sampler.clone()),
|
||||
tgt_color: self.tgt_color_view_pp.clone(),
|
||||
tgt_color: self.tgt_color_pp_view.clone(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -1,38 +1,22 @@
|
||||
use super::{gfx_backend, RenderError};
|
||||
use gfx::{self, traits::Factory};
|
||||
use super::RenderError;
|
||||
use image::{DynamicImage, GenericImageView};
|
||||
use vek::Vec2;
|
||||
|
||||
type DefaultShaderFormat = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb);
|
||||
use wgpu::{util::DeviceExt, Extent3d};
|
||||
|
||||
/// Represents an image that has been uploaded to the GPU.
|
||||
#[derive(Clone)]
|
||||
pub struct Texture<F: gfx::format::Formatted = DefaultShaderFormat>
|
||||
where
|
||||
F::Surface: gfx::format::TextureSurface,
|
||||
F::Channel: gfx::format::TextureChannel,
|
||||
<F::Surface as gfx::format::SurfaceTyped>::DataType: Copy,
|
||||
{
|
||||
pub tex: gfx::handle::Texture<gfx_backend::Resources, <F as gfx::format::Formatted>::Surface>,
|
||||
pub srv: gfx::handle::ShaderResourceView<
|
||||
gfx_backend::Resources,
|
||||
<F as gfx::format::Formatted>::View,
|
||||
>,
|
||||
pub sampler: gfx::handle::Sampler<gfx_backend::Resources>,
|
||||
pub struct Texture {
|
||||
pub tex: wgpu::TextureView,
|
||||
pub sampler: wgpu::Sampler,
|
||||
size: Extent3d,
|
||||
}
|
||||
|
||||
impl<F: gfx::format::Formatted> Texture<F>
|
||||
where
|
||||
F::Surface: gfx::format::TextureSurface,
|
||||
F::Channel: gfx::format::TextureChannel,
|
||||
<F::Surface as gfx::format::SurfaceTyped>::DataType: Copy,
|
||||
{
|
||||
impl Texture {
|
||||
pub fn new(
|
||||
factory: &mut gfx_backend::Factory,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
image: &DynamicImage,
|
||||
filter_method: Option<gfx::texture::FilterMethod>,
|
||||
wrap_mode: Option<gfx::texture::WrapMode>,
|
||||
border: Option<gfx::texture::PackedColor>,
|
||||
filter_method: Option<wgpu::FilterMode>,
|
||||
addresse_mode: Option<wgpu::AddressMode>,
|
||||
) -> Result<Self, RenderError> {
|
||||
// TODO: Actualy handle images that aren't in rgba format properly.
|
||||
let buffer = image.as_flat_samples_u8().ok_or_else(|| {
|
||||
@ -40,147 +24,143 @@ where
|
||||
"We currently do not support color formats using more than 4 bytes / pixel.".into(),
|
||||
)
|
||||
})?;
|
||||
let (tex, srv) = factory
|
||||
.create_texture_immutable_u8::<F>(
|
||||
gfx::texture::Kind::D2(
|
||||
image.width() as u16,
|
||||
image.height() as u16,
|
||||
gfx::texture::AaMode::Single,
|
||||
),
|
||||
gfx::texture::Mipmap::Provided,
|
||||
// Guarenteed to be correct, since all the conversions from DynamicImage to
|
||||
// FlatSamples<u8> go through the underlying ImageBuffer's implementation of
|
||||
// as_flat_samples(), which guarantees that the resulting FlatSamples is
|
||||
// well-formed.
|
||||
&[buffer.as_slice()],
|
||||
)
|
||||
.map_err(RenderError::CombinedError)?;
|
||||
|
||||
let mut sampler_info = gfx::texture::SamplerInfo::new(
|
||||
filter_method.unwrap_or(gfx::texture::FilterMethod::Scale),
|
||||
wrap_mode.unwrap_or(gfx::texture::WrapMode::Clamp),
|
||||
let size = Extent3d {
|
||||
width: image.width(),
|
||||
height: image.height(),
|
||||
depth: 1,
|
||||
};
|
||||
|
||||
let tex = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||
usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED,
|
||||
});
|
||||
|
||||
let mut command_encoder =
|
||||
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
|
||||
|
||||
queue.write_texture(
|
||||
wgpu::TextureCopyViewBase {
|
||||
texture: &tex,
|
||||
mip_level: 0,
|
||||
origin: wgpu::Origin3d::ZERO,
|
||||
},
|
||||
&[buffer.as_slice()],
|
||||
wgpu::TextureDataLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: image.width() * 4,
|
||||
rows_per_image: image.height(),
|
||||
},
|
||||
wgpu::Extent3d {
|
||||
width: image.width(),
|
||||
height: image.height(),
|
||||
depth: 1,
|
||||
},
|
||||
);
|
||||
let transparent = [0.0, 0.0, 0.0, 1.0].into();
|
||||
sampler_info.border = border.unwrap_or(transparent);
|
||||
|
||||
let sampler_info = wgpu::SamplerDescriptor {
|
||||
label: None,
|
||||
address_mode_u: addresse_mode.unwrap_or(wgpu::AddressMode::ClampToEdge),
|
||||
address_mode_v: addresse_mode.unwrap_or(wgpu::AddressMode::ClampToEdge),
|
||||
address_mode_w: addresse_mode.unwrap_or(wgpu::AddressMode::ClampToEdge),
|
||||
mag_filter: filter_method.unwrap_or(wgpu::FilterMode::Nearest),
|
||||
min_filter: filter_method.unwrap_or(wgpu::FilterMode::Nearest),
|
||||
mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
tex,
|
||||
srv,
|
||||
sampler: factory.create_sampler(sampler_info),
|
||||
sampler: device.create_sampler(&sampler_info),
|
||||
size,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_dynamic(
|
||||
factory: &mut gfx_backend::Factory,
|
||||
width: u16,
|
||||
height: u16,
|
||||
) -> Result<Self, RenderError> {
|
||||
let tex = factory.create_texture(
|
||||
gfx::texture::Kind::D2(
|
||||
pub fn new_dynamic(device: &wgpu::Device, width: u16, height: u16) -> Self {
|
||||
let size = wgpu::Extent3d {
|
||||
width,
|
||||
height,
|
||||
gfx::texture::AaMode::Single,
|
||||
),
|
||||
1_u8,
|
||||
gfx::memory::Bind::SHADER_RESOURCE,
|
||||
gfx::memory::Usage::Dynamic,
|
||||
Some(<<F as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type()),
|
||||
)
|
||||
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?;
|
||||
depth: 1,
|
||||
};
|
||||
|
||||
let srv = factory
|
||||
.view_texture_as_shader_resource::<F>(&tex, (0, 0), gfx::format::Swizzle::new())
|
||||
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Resource(err)))?;
|
||||
let tex_info = device.create_texture(&wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||
usage: wgpu::TextureUsage::COPY_DST | wgpu::TextureUsage::SAMPLED,
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
tex,
|
||||
srv,
|
||||
sampler: factory.create_sampler(gfx::texture::SamplerInfo::new(
|
||||
gfx::texture::FilterMethod::Scale,
|
||||
gfx::texture::WrapMode::Clamp,
|
||||
)),
|
||||
})
|
||||
}
|
||||
let sampler_info = wgpu::SamplerDescriptor {
|
||||
label: None,
|
||||
address_mode_u: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_v: wgpu::AddressMode::ClampToEdge,
|
||||
address_mode_w: wgpu::AddressMode::ClampToEdge,
|
||||
mag_filter: wgpu::FilterMode::Nearest,
|
||||
min_filter: wgpu::FilterMode::Nearest,
|
||||
mipmap_filter: wgpu::FilterMode::Nearest,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
pub fn new_immutable_raw(
|
||||
factory: &mut gfx_backend::Factory,
|
||||
kind: gfx::texture::Kind,
|
||||
mipmap: gfx::texture::Mipmap,
|
||||
data: &[&[<F::Surface as gfx::format::SurfaceTyped>::DataType]],
|
||||
sampler_info: gfx::texture::SamplerInfo,
|
||||
) -> Result<Self, RenderError> {
|
||||
let (tex, srv) = factory
|
||||
.create_texture_immutable::<F>(kind, mipmap, data)
|
||||
.map_err(RenderError::CombinedError)?;
|
||||
|
||||
Ok(Self {
|
||||
tex,
|
||||
srv,
|
||||
sampler: factory.create_sampler(sampler_info),
|
||||
})
|
||||
Self::new_raw(device, tex_info, sampler_info)
|
||||
}
|
||||
|
||||
pub fn new_raw(
|
||||
_device: &mut gfx_backend::Device,
|
||||
factory: &mut gfx_backend::Factory,
|
||||
kind: gfx::texture::Kind,
|
||||
max_levels: u8,
|
||||
bind: gfx::memory::Bind,
|
||||
usage: gfx::memory::Usage,
|
||||
levels: (u8, u8),
|
||||
swizzle: gfx::format::Swizzle,
|
||||
sampler_info: gfx::texture::SamplerInfo,
|
||||
) -> Result<Self, RenderError> {
|
||||
let tex = factory
|
||||
.create_texture(
|
||||
kind,
|
||||
max_levels as gfx::texture::Level,
|
||||
bind | gfx::memory::Bind::SHADER_RESOURCE,
|
||||
usage,
|
||||
Some(<<F as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type())
|
||||
)
|
||||
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?;
|
||||
|
||||
let srv = factory
|
||||
.view_texture_as_shader_resource::<F>(&tex, levels, swizzle)
|
||||
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Resource(err)))?;
|
||||
|
||||
device: &wgpu::Device,
|
||||
texture_info: wgpu::TextureDescriptor,
|
||||
sampler_info: wgpu::SamplerDescriptor,
|
||||
) -> Self {
|
||||
Ok(Self {
|
||||
tex,
|
||||
srv,
|
||||
sampler: factory.create_sampler(sampler_info),
|
||||
tex: device.create_texture(&texture_info),
|
||||
sampler: device.create_sampler(&sampler_info),
|
||||
size: texture_info.size,
|
||||
})
|
||||
}
|
||||
|
||||
/// Update a texture with the given data (used for updating the glyph cache
|
||||
/// texture).
|
||||
|
||||
pub fn update(
|
||||
&self,
|
||||
encoder: &mut gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
offset: [u16; 2],
|
||||
size: [u16; 2],
|
||||
data: &[<F::Surface as gfx::format::SurfaceTyped>::DataType],
|
||||
data: &[u8],
|
||||
) -> Result<(), RenderError> {
|
||||
let info = gfx::texture::ImageInfoCommon {
|
||||
xoffset: offset[0],
|
||||
yoffset: offset[1],
|
||||
zoffset: 0,
|
||||
// TODO: Only works for 2D images
|
||||
queue.write_texture(
|
||||
wgpu::TextureCopyViewBase {
|
||||
texture: &self.tex,
|
||||
mip_level: 0,
|
||||
origin: wgpu::Origin3d {
|
||||
x: offset[0],
|
||||
y: offset[1],
|
||||
z: 0,
|
||||
},
|
||||
},
|
||||
data,
|
||||
// TODO: I heard some rumors that there are other
|
||||
// formats that are not Rgba8
|
||||
wgpu::TextureDataLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: self.size.x * 4,
|
||||
rows_per_image: self.size.y,
|
||||
},
|
||||
wgpu::Extent3d {
|
||||
width: size[0],
|
||||
height: size[1],
|
||||
depth: 0,
|
||||
format: (),
|
||||
mipmap: 0,
|
||||
};
|
||||
encoder
|
||||
.update_texture::<<F as gfx::format::Formatted>::Surface, F>(
|
||||
&self.tex, None, info, data,
|
||||
)
|
||||
.map_err(RenderError::TexUpdateError)
|
||||
depth: 1,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Get dimensions of the represented image.
|
||||
pub fn get_dimensions(&self) -> Vec2<u16> {
|
||||
let (w, h, ..) = self.tex.get_info().kind.get_dimensions();
|
||||
Vec2::new(w, h)
|
||||
}
|
||||
pub fn get_dimensions(&self) -> Extent3d { self.size }
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
controller::*,
|
||||
render::{Renderer, WinColorFmt, WinDepthFmt},
|
||||
render::Renderer,
|
||||
settings::{ControlSettings, Settings},
|
||||
ui, Error,
|
||||
};
|
||||
@ -12,7 +12,7 @@ use itertools::Itertools;
|
||||
use keyboard_keynames::key_layout::KeyLayout;
|
||||
use old_school_gfx_glutin_ext::{ContextBuilderExt, WindowInitExt, WindowUpdateExt};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::{error, info, warn};
|
||||
use tracing::{error, warn};
|
||||
use vek::*;
|
||||
use winit::monitor::VideoMode;
|
||||
|
||||
@ -519,7 +519,7 @@ impl KeyMouse {
|
||||
|
||||
pub struct Window {
|
||||
renderer: Renderer,
|
||||
window: glutin::ContextWrapper<glutin::PossiblyCurrent, winit::window::Window>,
|
||||
window: winit::window::Window,
|
||||
cursor_grabbed: bool,
|
||||
pub pan_sensitivity: u32,
|
||||
pub zoom_sensitivity: u32,
|
||||
@ -565,26 +565,18 @@ impl Window {
|
||||
false,
|
||||
);
|
||||
|
||||
let (window, device, factory, win_color_view, win_depth_view) =
|
||||
glutin::ContextBuilder::new()
|
||||
.with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 3)))
|
||||
.with_vsync(false)
|
||||
.with_gfx_color_depth::<WinColorFmt, WinDepthFmt>()
|
||||
.build_windowed(win_builder, &event_loop)
|
||||
.map_err(|err| Error::BackendError(Box::new(err)))?
|
||||
.init_gfx::<WinColorFmt, WinDepthFmt>();
|
||||
// let (window, device, factory, win_color_view, win_depth_view) =
|
||||
// glutin::ContextBuilder::new()
|
||||
// .with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 3)))
|
||||
// .with_vsync(false)
|
||||
// .with_gfx_color_depth::<WinColorFmt, WinDepthFmt>()
|
||||
// .build_windowed(win_builder, &event_loop)
|
||||
// .map_err(|err| Error::BackendError(Box::new(err)))?
|
||||
// .init_gfx::<WinColorFmt, WinDepthFmt>();
|
||||
|
||||
let vendor = device.get_info().platform_name.vendor;
|
||||
let renderer = device.get_info().platform_name.renderer;
|
||||
let opengl_version = device.get_info().version;
|
||||
let glsl_version = device.get_info().shading_language;
|
||||
info!(
|
||||
?vendor,
|
||||
?renderer,
|
||||
?opengl_version,
|
||||
?glsl_version,
|
||||
"selected graphics device"
|
||||
);
|
||||
let window = win_builder.build(&event_loop)?;
|
||||
|
||||
let renderer = Renderer::new(&window, settings.graphics.render_mode.clone())?;
|
||||
|
||||
let keypress_map = HashMap::new();
|
||||
|
||||
@ -632,13 +624,7 @@ impl Window {
|
||||
};
|
||||
|
||||
let mut this = Self {
|
||||
renderer: Renderer::new(
|
||||
device,
|
||||
factory,
|
||||
win_color_view,
|
||||
win_depth_view,
|
||||
settings.graphics.render_mode.clone(),
|
||||
)?,
|
||||
renderer,
|
||||
window,
|
||||
cursor_grabbed: false,
|
||||
pan_sensitivity: settings.gameplay.pan_sensitivity,
|
||||
@ -1367,7 +1353,7 @@ impl Window {
|
||||
pub fn set_size(&mut self, new_size: Vec2<u16>) {
|
||||
self.window
|
||||
.window()
|
||||
.set_inner_size(glutin::dpi::LogicalSize::new(
|
||||
.set_inner_size(winit::dpi::LogicalSize::new(
|
||||
new_size.x as f64,
|
||||
new_size.y as f64,
|
||||
));
|
||||
|
Loading…
Reference in New Issue
Block a user