Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/metal/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/metal/.cargo-checksum.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1516
third-party/vendor/metal/Cargo.lock
generated
vendored
Normal file
1516
third-party/vendor/metal/Cargo.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
144
third-party/vendor/metal/Cargo.toml
vendored
Normal file
144
third-party/vendor/metal/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
name = "metal"
|
||||
version = "0.26.0"
|
||||
authors = ["gfx-rs developers"]
|
||||
exclude = [
|
||||
"guide/**/*",
|
||||
"examples/texture/**/*",
|
||||
"tests/**/*",
|
||||
"Cargo.lock",
|
||||
"target/**/*",
|
||||
]
|
||||
description = "Rust bindings for Metal"
|
||||
homepage = "https://github.com/gfx-rs/metal-rs"
|
||||
documentation = "https://docs.rs/crate/metal"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"metal",
|
||||
"graphics",
|
||||
"bindings",
|
||||
]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/gfx-rs/metal-rs"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
default-target = "x86_64-apple-darwin"
|
||||
|
||||
[[example]]
|
||||
name = "window"
|
||||
|
||||
[[example]]
|
||||
name = "headless-render"
|
||||
|
||||
[[example]]
|
||||
name = "library"
|
||||
|
||||
[[example]]
|
||||
name = "raytracing"
|
||||
|
||||
[[example]]
|
||||
name = "reflection"
|
||||
|
||||
[[example]]
|
||||
name = "caps"
|
||||
|
||||
[[example]]
|
||||
name = "argument-buffer"
|
||||
|
||||
[[example]]
|
||||
name = "bindless"
|
||||
|
||||
[[example]]
|
||||
name = "circle"
|
||||
path = "examples/circle/main.rs"
|
||||
|
||||
[[example]]
|
||||
name = "compute"
|
||||
path = "examples/compute/main.rs"
|
||||
|
||||
[[example]]
|
||||
name = "mps"
|
||||
required-features = ["mps"]
|
||||
|
||||
[[example]]
|
||||
name = "embedded-lib"
|
||||
path = "examples/compute/embedded-lib.rs"
|
||||
|
||||
[[example]]
|
||||
name = "compute-argument-buffer"
|
||||
path = "examples/compute/compute-argument-buffer.rs"
|
||||
|
||||
[[example]]
|
||||
name = "bind"
|
||||
|
||||
[[example]]
|
||||
name = "events"
|
||||
required-features = ["dispatch"]
|
||||
|
||||
[[example]]
|
||||
name = "fence"
|
||||
|
||||
[dependencies.bitflags]
|
||||
version = "2"
|
||||
|
||||
[dependencies.block]
|
||||
version = "0.1.6"
|
||||
|
||||
[dependencies.core-graphics-types]
|
||||
version = "0.1"
|
||||
|
||||
[dependencies.dispatch]
|
||||
version = "0.2"
|
||||
optional = true
|
||||
|
||||
[dependencies.foreign-types]
|
||||
version = "0.5"
|
||||
|
||||
[dependencies.log]
|
||||
version = "0.4"
|
||||
|
||||
[dependencies.objc]
|
||||
version = "0.2.4"
|
||||
features = ["objc_exception"]
|
||||
|
||||
[dependencies.paste]
|
||||
version = "1"
|
||||
|
||||
[dev-dependencies.cocoa]
|
||||
version = "0.24.0"
|
||||
|
||||
[dev-dependencies.cty]
|
||||
version = "0.2.1"
|
||||
|
||||
[dev-dependencies.glam]
|
||||
version = "0.22"
|
||||
|
||||
[dev-dependencies.png]
|
||||
version = "0.17"
|
||||
|
||||
[dev-dependencies.rand]
|
||||
version = "0.8"
|
||||
|
||||
[dev-dependencies.sema]
|
||||
version = "0.1.4"
|
||||
|
||||
[dev-dependencies.winit]
|
||||
version = "0.27"
|
||||
|
||||
[features]
|
||||
default = ["link"]
|
||||
link = []
|
||||
mps = []
|
||||
private = []
|
||||
201
third-party/vendor/metal/LICENSE-APACHE
vendored
Normal file
201
third-party/vendor/metal/LICENSE-APACHE
vendored
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
25
third-party/vendor/metal/LICENSE-MIT
vendored
Normal file
25
third-party/vendor/metal/LICENSE-MIT
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
Copyright (c) 2010 The Rust Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
16
third-party/vendor/metal/Makefile
vendored
Normal file
16
third-party/vendor/metal/Makefile
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
compute:
|
||||
xcrun -sdk macosx metal -c examples/compute/shaders.metal -o examples/compute/shaders.air
|
||||
xcrun -sdk macosx metallib examples/compute/shaders.air -o examples/compute/shaders.metallib
|
||||
|
||||
window:
|
||||
xcrun -sdk macosx metal -c examples/window/shaders.metal -o examples/window/shaders.air
|
||||
xcrun -sdk macosx metallib examples/window/shaders.air -o examples/window/shaders.metallib
|
||||
|
||||
circle:
|
||||
xcrun -sdk macosx metal -c examples/circle/shaders.metal -o examples/circle/shaders.air
|
||||
xcrun -sdk macosx metallib examples/circle/shaders.air -o examples/circle/shaders.metallib
|
||||
|
||||
raytracing:
|
||||
xcrun -sdk macosx metal -c -g examples/raytracing/shaders.metal -o examples/raytracing/shaders.air
|
||||
xcrun -sdk macosx metallib examples/raytracing/shaders.air -o examples/raytracing/shaders.metallib
|
||||
43
third-party/vendor/metal/README.md
vendored
Normal file
43
third-party/vendor/metal/README.md
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# metal-rs
|
||||
[](https://github.com/gfx-rs/metal-rs/actions)
|
||||
[](https://crates.io/crates/metal)
|
||||
|
||||
<p align="center">
|
||||
<img width="150" height="150" src="./assets/metal.svg">
|
||||
</p>
|
||||
|
||||
<p align="center">Unsafe Rust bindings for the Metal 3D Graphics API.</p>
|
||||
|
||||
## Documentation
|
||||
|
||||
Note that [docs.rs](docs.rs) will fail to build the (albeit limited) documentation for this crate!
|
||||
They build in a Linux container, but of course this will only compile on MacOS.
|
||||
|
||||
Please build the documentation yourself with `cargo docs`.
|
||||
|
||||
## Examples
|
||||
|
||||
The [examples](/examples) directory highlights different ways of using the Metal graphics API for rendering
|
||||
and computation.
|
||||
|
||||
Examples can be run using commands such as:
|
||||
|
||||
```
|
||||
# Replace `window` with the name of the example that you would like to run
|
||||
cargo run --example window
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Licensed under either of
|
||||
|
||||
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
|
||||
dual licensed as above, without any additional terms or conditions.
|
||||
15
third-party/vendor/metal/assets/metal.svg
vendored
Normal file
15
third-party/vendor/metal/assets/metal.svg
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="720px" height="720px" viewBox="0 0 720 720" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="limeGradient">
|
||||
<stop stop-color="#0EFFDD" offset="0%"></stop>
|
||||
<stop stop-color="#24FF74" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M576,720 L144,720 C64.5,720 0,655.5 0,576 L0,144 C0,64.5 64.5,0 144,0 L576,0 C655.5,0 720,64.5 720,144 L720,576 C720,655.5 655.5,720 576,720 Z" id="app-backplate" fill="url(#limeGradient)"></path>
|
||||
<polygon id="Path" fill="#000000" points="141 132 334 368 334 195 651 545 569 545 398 364 396 545 205 309 205 545 141 545"></polygon>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 848 B |
8
third-party/vendor/metal/bors.toml
vendored
Normal file
8
third-party/vendor/metal/bors.toml
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
status = [ "build (stable)" ]
|
||||
|
||||
# As of May 2020 we can expect CI to take roughly 3 minutes based on
|
||||
# Based on https://github.com/chinedufn/metal-rs/actions/runs/94020785
|
||||
#
|
||||
# We round this up to a timeout of 5 minutes to account for any potential future
|
||||
# inconsistencies in CI run times.
|
||||
timeout-sec = 300
|
||||
88
third-party/vendor/metal/examples/argument-buffer/main.rs
vendored
Normal file
88
third-party/vendor/metal/examples/argument-buffer/main.rs
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright 2017 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use metal::*;
|
||||
use objc::rc::autoreleasepool;
|
||||
|
||||
fn main() {
|
||||
autoreleasepool(|| {
|
||||
let device = Device::system_default().expect("no device found");
|
||||
|
||||
/*
|
||||
|
||||
// Build encoder for the following MSL argument buffer:
|
||||
struct ArgumentBuffer {
|
||||
texture2d<float> texture [[id(0)]];
|
||||
sampler sampler [[id(1)]];
|
||||
array<device float *, 2> buffers [[id(2)]];
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
let desc1 = ArgumentDescriptor::new();
|
||||
desc1.set_index(0);
|
||||
desc1.set_data_type(MTLDataType::Texture);
|
||||
desc1.set_texture_type(MTLTextureType::D2);
|
||||
|
||||
let desc2 = ArgumentDescriptor::new();
|
||||
desc2.set_index(1);
|
||||
desc2.set_data_type(MTLDataType::Sampler);
|
||||
|
||||
let desc3 = ArgumentDescriptor::new();
|
||||
desc3.set_index(2);
|
||||
desc3.set_data_type(MTLDataType::Pointer);
|
||||
desc3.set_array_length(2);
|
||||
|
||||
let encoder = device.new_argument_encoder(Array::from_slice(&[desc1, desc2, desc3]));
|
||||
println!("Encoder: {:?}", encoder);
|
||||
|
||||
let argument_buffer =
|
||||
device.new_buffer(encoder.encoded_length(), MTLResourceOptions::empty());
|
||||
encoder.set_argument_buffer(&argument_buffer, 0);
|
||||
|
||||
let sampler = {
|
||||
let descriptor = SamplerDescriptor::new();
|
||||
descriptor.set_support_argument_buffers(true);
|
||||
device.new_sampler(&descriptor)
|
||||
};
|
||||
println!("{:?}", sampler);
|
||||
|
||||
let buffer1 = device.new_buffer(1024, MTLResourceOptions::empty());
|
||||
println!("Buffer1: {:?}", buffer1);
|
||||
let buffer2 = device.new_buffer(1024, MTLResourceOptions::empty());
|
||||
println!("Buffer2: {:?}", buffer2);
|
||||
|
||||
encoder.set_sampler_state(1, &sampler);
|
||||
encoder.set_buffer(2, &buffer1, 0);
|
||||
encoder.set_buffer(3, &buffer2, 0);
|
||||
|
||||
// How to use argument buffer with render encoder.
|
||||
|
||||
let queue = device.new_command_queue();
|
||||
let command_buffer = queue.new_command_buffer();
|
||||
|
||||
let render_pass_descriptor = RenderPassDescriptor::new();
|
||||
let encoder = command_buffer.new_render_command_encoder(render_pass_descriptor);
|
||||
|
||||
// This method makes the array of resources resident for the selected stages of the render pass.
|
||||
// Call this method before issuing any draw calls that may access the array of resources.
|
||||
encoder.use_resources(
|
||||
&[&buffer1, &buffer2],
|
||||
MTLResourceUsage::Read,
|
||||
MTLRenderStages::Vertex,
|
||||
);
|
||||
// Bind argument buffer to vertex stage.
|
||||
encoder.set_vertex_buffer(0, Some(&argument_buffer), 0);
|
||||
|
||||
// Render pass here...
|
||||
|
||||
encoder.end_encoding();
|
||||
println!("Encoder: {:?}", encoder);
|
||||
|
||||
command_buffer.commit();
|
||||
});
|
||||
}
|
||||
34
third-party/vendor/metal/examples/bind/main.rs
vendored
Normal file
34
third-party/vendor/metal/examples/bind/main.rs
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2018 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use metal::*;
|
||||
use objc::rc::autoreleasepool;
|
||||
|
||||
fn main() {
|
||||
autoreleasepool(|| {
|
||||
let device = Device::system_default().expect("no device found");
|
||||
|
||||
let buffer = device.new_buffer(4, MTLResourceOptions::empty());
|
||||
let sampler = {
|
||||
let descriptor = SamplerDescriptor::new();
|
||||
device.new_sampler(&descriptor)
|
||||
};
|
||||
|
||||
let queue = device.new_command_queue();
|
||||
let cmd_buf = queue.new_command_buffer();
|
||||
|
||||
let encoder = cmd_buf.new_compute_command_encoder();
|
||||
|
||||
encoder.set_buffers(2, &[Some(&buffer), None], &[4, 0]);
|
||||
encoder.set_sampler_states(1, &[Some(&sampler), None]);
|
||||
|
||||
encoder.end_encoding();
|
||||
cmd_buf.commit();
|
||||
|
||||
println!("Everything is bound");
|
||||
});
|
||||
}
|
||||
149
third-party/vendor/metal/examples/bindless/main.rs
vendored
Normal file
149
third-party/vendor/metal/examples/bindless/main.rs
vendored
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
// Copyright 2017 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use metal::*;
|
||||
use objc::rc::autoreleasepool;
|
||||
|
||||
const BINDLESS_TEXTURE_COUNT: NSUInteger = 100_000; // ~25Mb
|
||||
|
||||
/// This example demonstrates:
|
||||
/// - How to create a heap
|
||||
/// - How to allocate textures from heap.
|
||||
/// - How to create bindless resources via Metal's argument buffers.
|
||||
/// - How to bind argument buffer to render encoder
|
||||
fn main() {
|
||||
autoreleasepool(|| {
|
||||
let device = Device::system_default().expect("no device found");
|
||||
|
||||
/*
|
||||
|
||||
MSL
|
||||
|
||||
struct Textures {
|
||||
texture2d<float> texture;
|
||||
};
|
||||
struct BindlessTextures {
|
||||
device Textures *textures;
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
// Tier 2 argument buffers are supported by macOS devices with a discrete GPU and by the A13 GPU.
|
||||
// The maximum per-app resources available at any given time are:
|
||||
// - 500,000 buffers or textures
|
||||
// - 2048 unique samplers
|
||||
let tier = device.argument_buffers_support();
|
||||
println!("Argument buffer support: {:?}", tier);
|
||||
assert_eq!(MTLArgumentBuffersTier::Tier2, tier);
|
||||
|
||||
let texture_descriptor = TextureDescriptor::new();
|
||||
texture_descriptor.set_width(1);
|
||||
texture_descriptor.set_height(1);
|
||||
texture_descriptor.set_depth(1);
|
||||
texture_descriptor.set_texture_type(MTLTextureType::D2);
|
||||
texture_descriptor.set_pixel_format(MTLPixelFormat::R8Uint);
|
||||
texture_descriptor.set_storage_mode(MTLStorageMode::Private); // GPU only.
|
||||
println!("Texture descriptor: {:?}", texture_descriptor);
|
||||
|
||||
// Determine the size required for the heap for the given descriptor
|
||||
let size_and_align = device.heap_texture_size_and_align(&texture_descriptor);
|
||||
|
||||
// Align the size so that more resources will fit in the heap after this texture
|
||||
// See https://developer.apple.com/documentation/metal/buffers/using_argument_buffers_with_resource_heaps
|
||||
let texture_size =
|
||||
(size_and_align.size & (size_and_align.align - 1)) + size_and_align.align;
|
||||
let heap_size = texture_size * BINDLESS_TEXTURE_COUNT;
|
||||
|
||||
let heap_descriptor = HeapDescriptor::new();
|
||||
heap_descriptor.set_storage_mode(texture_descriptor.storage_mode()); // Must be compatible
|
||||
heap_descriptor.set_size(heap_size);
|
||||
println!("Heap descriptor: {:?}", heap_descriptor);
|
||||
|
||||
let heap = device.new_heap(&heap_descriptor);
|
||||
println!("Heap: {:?}", heap);
|
||||
|
||||
// Allocate textures from heap
|
||||
let textures = (0..BINDLESS_TEXTURE_COUNT)
|
||||
.map(|i| {
|
||||
heap.new_texture(&texture_descriptor)
|
||||
.expect(&format!("Failed to allocate texture {}", i))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Crate argument encoder that knows how to encode single texture
|
||||
let descriptor = ArgumentDescriptor::new();
|
||||
descriptor.set_index(0);
|
||||
descriptor.set_data_type(MTLDataType::Texture);
|
||||
descriptor.set_texture_type(MTLTextureType::D2);
|
||||
descriptor.set_access(MTLArgumentAccess::ReadOnly);
|
||||
println!("Argument descriptor: {:?}", descriptor);
|
||||
|
||||
let encoder = device.new_argument_encoder(Array::from_slice(&[descriptor]));
|
||||
println!("Encoder: {:?}", encoder);
|
||||
|
||||
// Determinate argument buffer size to allocate.
|
||||
// Size needed to encode one texture * total number of bindless textures.
|
||||
let argument_buffer_size = encoder.encoded_length() * BINDLESS_TEXTURE_COUNT;
|
||||
let argument_buffer = device.new_buffer(argument_buffer_size, MTLResourceOptions::empty());
|
||||
|
||||
// Encode textures to the argument buffer.
|
||||
textures.iter().enumerate().for_each(|(index, texture)| {
|
||||
// Offset encoder to a proper texture slot
|
||||
let offset = index as NSUInteger * encoder.encoded_length();
|
||||
encoder.set_argument_buffer(&argument_buffer, offset);
|
||||
encoder.set_texture(0, texture);
|
||||
});
|
||||
|
||||
// How to use bindless argument buffer when drawing
|
||||
|
||||
let queue = device.new_command_queue();
|
||||
let command_buffer = queue.new_command_buffer();
|
||||
|
||||
let render_pass_descriptor = RenderPassDescriptor::new();
|
||||
let encoder = command_buffer.new_render_command_encoder(render_pass_descriptor);
|
||||
|
||||
// Bind argument buffer.
|
||||
encoder.set_fragment_buffer(0, Some(&argument_buffer), 0);
|
||||
// Make sure all textures are available to the pass.
|
||||
encoder.use_heap_at(&heap, MTLRenderStages::Fragment);
|
||||
|
||||
// Bind material buffer at index 1
|
||||
// Draw
|
||||
|
||||
/*
|
||||
|
||||
// Now instead of binding individual textures each draw call,
|
||||
// you can just bind material information instead:
|
||||
|
||||
MSL
|
||||
|
||||
struct Material {
|
||||
int diffuse_texture_index;
|
||||
int normal_texture_index;
|
||||
// ...
|
||||
}
|
||||
|
||||
fragment float4 pixel(
|
||||
VertexOut v [[stage_in]],
|
||||
constant const BindlessTextures * textures [[buffer(0)]],
|
||||
constant Material * material [[buffer(1)]]
|
||||
) {
|
||||
if (material->base_color_texture_index != -1) {
|
||||
textures[material->diffuse_texture_index].texture.sampler(...)
|
||||
}
|
||||
if (material->normal_texture_index != -1) {
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
encoder.end_encoding();
|
||||
command_buffer.commit();
|
||||
});
|
||||
}
|
||||
33
third-party/vendor/metal/examples/caps/main.rs
vendored
Normal file
33
third-party/vendor/metal/examples/caps/main.rs
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2017 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use metal::*;
|
||||
|
||||
fn main() {
|
||||
let device = Device::system_default().expect("no device found");
|
||||
|
||||
#[cfg(feature = "private")]
|
||||
{
|
||||
println!("Vendor: {:?}", unsafe { device.vendor() });
|
||||
println!("Family: {:?}", unsafe { device.family_name() });
|
||||
}
|
||||
println!(
|
||||
"Max threads per threadgroup: {:?}",
|
||||
device.max_threads_per_threadgroup()
|
||||
);
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
println!("Integrated GPU: {:?}", device.is_low_power());
|
||||
println!("Headless: {:?}", device.is_headless());
|
||||
println!("D24S8: {:?}", device.d24_s8_supported());
|
||||
}
|
||||
println!("maxBufferLength: {} Mb", device.max_buffer_length() >> 20);
|
||||
println!(
|
||||
"Indirect argument buffer: {:?}",
|
||||
device.argument_buffers_support()
|
||||
);
|
||||
}
|
||||
11
third-party/vendor/metal/examples/circle/README.md
vendored
Normal file
11
third-party/vendor/metal/examples/circle/README.md
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
## circle
|
||||
|
||||
Renders a circle in a window. As metal primitive types are only limited to point, line and triangle shape, this example shows how we can form complex structures out of primitive types.
|
||||
|
||||

|
||||
|
||||
## To Run
|
||||
|
||||
```
|
||||
cargo run --example circle
|
||||
```
|
||||
377
third-party/vendor/metal/examples/circle/main.rs
vendored
Normal file
377
third-party/vendor/metal/examples/circle/main.rs
vendored
Normal file
|
|
@ -0,0 +1,377 @@
|
|||
use metal::*;
|
||||
|
||||
use winit::{
|
||||
event::{Event, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
platform::macos::WindowExtMacOS,
|
||||
};
|
||||
|
||||
use cocoa::{appkit::NSView, base::id as cocoa_id};
|
||||
use core_graphics_types::geometry::CGSize;
|
||||
|
||||
use objc::{rc::autoreleasepool, runtime::YES};
|
||||
|
||||
use std::mem;
|
||||
|
||||
// Declare the data structures needed to carry vertex layout to
|
||||
// metal shading language(MSL) program. Use #[repr(C)], to make
|
||||
// the data structure compatible with C++ type data structure
|
||||
// for vertex defined in MSL program as MSL program is broadly
|
||||
// based on C++
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct position(cty::c_float, cty::c_float);
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct color(cty::c_float, cty::c_float, cty::c_float);
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
pub struct AAPLVertex {
|
||||
p: position,
|
||||
c: color,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Create a window for viewing the content
|
||||
let event_loop = EventLoop::new();
|
||||
let size = winit::dpi::LogicalSize::new(800, 600);
|
||||
|
||||
let window = winit::window::WindowBuilder::new()
|
||||
.with_inner_size(size)
|
||||
.with_title("Metal".to_string())
|
||||
.build(&event_loop)
|
||||
.unwrap();
|
||||
|
||||
// Set up the GPU device found in the system
|
||||
let device = Device::system_default().expect("no device found");
|
||||
println!("Your device is: {}", device.name(),);
|
||||
|
||||
// Scaffold required to sample the GPU and CPU timestamps
|
||||
let mut cpu_start = 0;
|
||||
let mut gpu_start = 0;
|
||||
device.sample_timestamps(&mut cpu_start, &mut gpu_start);
|
||||
let counter_sample_buffer = create_counter_sample_buffer(&device);
|
||||
let destination_buffer = device.new_buffer(
|
||||
(std::mem::size_of::<u64>() * 4 as usize) as u64,
|
||||
MTLResourceOptions::StorageModeShared,
|
||||
);
|
||||
let counter_sampling_point = MTLCounterSamplingPoint::AtStageBoundary;
|
||||
assert!(device.supports_counter_sampling(counter_sampling_point));
|
||||
|
||||
let binary_archive_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("examples/circle/binary_archive.metallib");
|
||||
|
||||
let binary_archive_url =
|
||||
URL::new_with_string(&format!("file://{}", binary_archive_path.display()));
|
||||
|
||||
let binary_archive_descriptor = BinaryArchiveDescriptor::new();
|
||||
if binary_archive_path.exists() {
|
||||
binary_archive_descriptor.set_url(&binary_archive_url);
|
||||
}
|
||||
|
||||
// Set up a binary archive to cache compiled shaders.
|
||||
let binary_archive = device
|
||||
.new_binary_archive_with_descriptor(&binary_archive_descriptor)
|
||||
.unwrap();
|
||||
|
||||
let library_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("examples/circle/shaders.metallib");
|
||||
|
||||
// Use the metallib file generated out of .metal shader file
|
||||
let library = device.new_library_with_file(library_path).unwrap();
|
||||
|
||||
// The render pipeline generated from the vertex and fragment shaders in the .metal shader file.
|
||||
let pipeline_state = prepare_pipeline_state(&device, &library, &binary_archive);
|
||||
|
||||
// Serialize the binary archive to disk.
|
||||
binary_archive
|
||||
.serialize_to_url(&binary_archive_url)
|
||||
.unwrap();
|
||||
|
||||
// Set the command queue used to pass commands to the device.
|
||||
let command_queue = device.new_command_queue();
|
||||
|
||||
// Currently, MetalLayer is the only interface that provide
|
||||
// layers to carry drawable texture from GPU rendaring through metal
|
||||
// library to viewable windows.
|
||||
let layer = MetalLayer::new();
|
||||
layer.set_device(&device);
|
||||
layer.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
|
||||
layer.set_presents_with_transaction(false);
|
||||
|
||||
unsafe {
|
||||
let view = window.ns_view() as cocoa_id;
|
||||
view.setWantsLayer(YES);
|
||||
view.setLayer(mem::transmute(layer.as_ref()));
|
||||
}
|
||||
|
||||
let draw_size = window.inner_size();
|
||||
layer.set_drawable_size(CGSize::new(draw_size.width as f64, draw_size.height as f64));
|
||||
|
||||
let vbuf = {
|
||||
let vertex_data = create_vertex_points_for_circle();
|
||||
let vertex_data = vertex_data.as_slice();
|
||||
|
||||
device.new_buffer_with_data(
|
||||
vertex_data.as_ptr() as *const _,
|
||||
(vertex_data.len() * mem::size_of::<AAPLVertex>()) as u64,
|
||||
MTLResourceOptions::CPUCacheModeDefaultCache | MTLResourceOptions::StorageModeManaged,
|
||||
)
|
||||
};
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
autoreleasepool(|| {
|
||||
// ControlFlow::Wait pauses the event loop if no events are available to process.
|
||||
// This is ideal for non-game applications that only update in response to user
|
||||
// input, and uses significantly less power/CPU time than ControlFlow::Poll.
|
||||
*control_flow = ControlFlow::Wait;
|
||||
|
||||
match event {
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::CloseRequested,
|
||||
..
|
||||
} => {
|
||||
println!("The close button was pressed; stopping");
|
||||
*control_flow = ControlFlow::Exit
|
||||
}
|
||||
Event::MainEventsCleared => {
|
||||
// Queue a RedrawRequested event.
|
||||
window.request_redraw();
|
||||
}
|
||||
Event::RedrawRequested(_) => {
|
||||
// It's preferrable to render in this event rather than in MainEventsCleared, since
|
||||
// rendering in here allows the program to gracefully handle redraws requested
|
||||
// by the OS.
|
||||
let drawable = match layer.next_drawable() {
|
||||
Some(drawable) => drawable,
|
||||
None => return,
|
||||
};
|
||||
|
||||
// Create a new command buffer for each render pass to the current drawable
|
||||
let command_buffer = command_queue.new_command_buffer();
|
||||
|
||||
// Obtain a renderPassDescriptor generated from the view's drawable textures.
|
||||
let render_pass_descriptor = RenderPassDescriptor::new();
|
||||
handle_render_pass_color_attachment(
|
||||
&render_pass_descriptor,
|
||||
drawable.texture(),
|
||||
);
|
||||
handle_render_pass_sample_buffer_attachment(
|
||||
&render_pass_descriptor,
|
||||
&counter_sample_buffer,
|
||||
);
|
||||
|
||||
// Create a render command encoder.
|
||||
let encoder =
|
||||
command_buffer.new_render_command_encoder(&render_pass_descriptor);
|
||||
encoder.set_render_pipeline_state(&pipeline_state);
|
||||
// Pass in the parameter data.
|
||||
encoder.set_vertex_buffer(0, Some(&vbuf), 0);
|
||||
// Draw the triangles which will eventually form the circle.
|
||||
encoder.draw_primitives(MTLPrimitiveType::TriangleStrip, 0, 1080);
|
||||
encoder.end_encoding();
|
||||
|
||||
resolve_samples_into_buffer(
|
||||
&command_buffer,
|
||||
&counter_sample_buffer,
|
||||
&destination_buffer,
|
||||
);
|
||||
|
||||
// Schedule a present once the framebuffer is complete using the current drawable.
|
||||
command_buffer.present_drawable(&drawable);
|
||||
|
||||
// Finalize rendering here & push the command buffer to the GPU.
|
||||
command_buffer.commit();
|
||||
command_buffer.wait_until_completed();
|
||||
|
||||
let mut cpu_end = 0;
|
||||
let mut gpu_end = 0;
|
||||
device.sample_timestamps(&mut cpu_end, &mut gpu_end);
|
||||
handle_timestamps(&destination_buffer, cpu_start, cpu_end, gpu_start, gpu_end);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// If we want to draw a circle, we need to draw it out of the three primitive
|
||||
// types available with metal framework. Triangle is used in this case to form
|
||||
// the circle. If we consider a circle to be total of 360 degree at center, we
|
||||
// can form small triangle with one point at origin and two points at the
|
||||
// perimeter of the circle for each degree. Eventually, if we can take enough
|
||||
// triangle virtices for total of 360 degree, the triangles together will
|
||||
// form a circle. This function captures the triangle vertices for each degree
|
||||
// and push the co-ordinates of the vertices to a rust vector
|
||||
fn create_vertex_points_for_circle() -> Vec<AAPLVertex> {
|
||||
let mut v: Vec<AAPLVertex> = Vec::new();
|
||||
let origin_x: f32 = 0.0;
|
||||
let origin_y: f32 = 0.0;
|
||||
|
||||
// Size of the circle
|
||||
let circle_size = 0.8f32;
|
||||
|
||||
for i in 0..720 {
|
||||
let y = i as f32;
|
||||
// Get the X co-ordinate of each point on the perimeter of circle
|
||||
let position_x: f32 = y.to_radians().cos() * 100.0;
|
||||
let position_x: f32 = position_x.trunc() / 100.0;
|
||||
// Set the size of the circle
|
||||
let position_x: f32 = position_x * circle_size;
|
||||
// Get the Y co-ordinate of each point on the perimeter of circle
|
||||
let position_y: f32 = y.to_radians().sin() * 100.0;
|
||||
let position_y: f32 = position_y.trunc() / 100.0;
|
||||
// Set the size of the circle
|
||||
let position_y: f32 = position_y * circle_size;
|
||||
|
||||
v.push(AAPLVertex {
|
||||
p: position(position_x, position_y),
|
||||
c: color(0.7, 0.3, 0.5),
|
||||
});
|
||||
|
||||
if (i + 1) % 2 == 0 {
|
||||
// For each two points on perimeter, push one point of origin
|
||||
v.push(AAPLVertex {
|
||||
p: position(origin_x, origin_y),
|
||||
c: color(0.2, 0.7, 0.4),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
v
|
||||
}
|
||||
|
||||
fn handle_render_pass_sample_buffer_attachment(
|
||||
descriptor: &RenderPassDescriptorRef,
|
||||
counter_sample_buffer: &CounterSampleBufferRef,
|
||||
) {
|
||||
let sample_buffer_attachment_descriptor =
|
||||
descriptor.sample_buffer_attachments().object_at(0).unwrap();
|
||||
sample_buffer_attachment_descriptor.set_sample_buffer(&counter_sample_buffer);
|
||||
sample_buffer_attachment_descriptor.set_start_of_vertex_sample_index(0 as NSUInteger);
|
||||
sample_buffer_attachment_descriptor.set_end_of_vertex_sample_index(1 as NSUInteger);
|
||||
sample_buffer_attachment_descriptor.set_start_of_fragment_sample_index(2 as NSUInteger);
|
||||
sample_buffer_attachment_descriptor.set_end_of_fragment_sample_index(3 as NSUInteger);
|
||||
}
|
||||
|
||||
fn handle_render_pass_color_attachment(descriptor: &RenderPassDescriptorRef, texture: &TextureRef) {
|
||||
let color_attachment = descriptor.color_attachments().object_at(0).unwrap();
|
||||
|
||||
color_attachment.set_texture(Some(texture));
|
||||
color_attachment.set_load_action(MTLLoadAction::Clear);
|
||||
// Setting a background color
|
||||
color_attachment.set_clear_color(MTLClearColor::new(0.5, 0.5, 0.8, 1.0));
|
||||
color_attachment.set_store_action(MTLStoreAction::Store);
|
||||
}
|
||||
|
||||
fn prepare_pipeline_state(
|
||||
device: &Device,
|
||||
library: &Library,
|
||||
binary_archive: &BinaryArchive,
|
||||
) -> RenderPipelineState {
|
||||
let vert = library.get_function("vs", None).unwrap();
|
||||
let frag = library.get_function("ps", None).unwrap();
|
||||
|
||||
let pipeline_state_descriptor = RenderPipelineDescriptor::new();
|
||||
pipeline_state_descriptor.set_vertex_function(Some(&vert));
|
||||
pipeline_state_descriptor.set_fragment_function(Some(&frag));
|
||||
pipeline_state_descriptor
|
||||
.color_attachments()
|
||||
.object_at(0)
|
||||
.unwrap()
|
||||
.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
|
||||
// Set the binary archives to search for a cached pipeline in.
|
||||
pipeline_state_descriptor.set_binary_archives(&[binary_archive]);
|
||||
|
||||
// Add the pipeline descriptor to the binary archive cache.
|
||||
binary_archive
|
||||
.add_render_pipeline_functions_with_descriptor(&pipeline_state_descriptor)
|
||||
.unwrap();
|
||||
|
||||
device
|
||||
.new_render_pipeline_state(&pipeline_state_descriptor)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn resolve_samples_into_buffer(
|
||||
command_buffer: &CommandBufferRef,
|
||||
counter_sample_buffer: &CounterSampleBufferRef,
|
||||
destination_buffer: &BufferRef,
|
||||
) {
|
||||
let blit_encoder = command_buffer.new_blit_command_encoder();
|
||||
blit_encoder.resolve_counters(
|
||||
&counter_sample_buffer,
|
||||
crate::NSRange::new(0_u64, 4),
|
||||
&destination_buffer,
|
||||
0_u64,
|
||||
);
|
||||
blit_encoder.end_encoding();
|
||||
}
|
||||
|
||||
fn handle_timestamps(
|
||||
resolved_sample_buffer: &BufferRef,
|
||||
cpu_start: u64,
|
||||
cpu_end: u64,
|
||||
gpu_start: u64,
|
||||
gpu_end: u64,
|
||||
) {
|
||||
let samples = unsafe {
|
||||
std::slice::from_raw_parts(resolved_sample_buffer.contents() as *const u64, 4 as usize)
|
||||
};
|
||||
let vertex_pass_start = samples[0];
|
||||
let vertex_pass_end = samples[1];
|
||||
let fragment_pass_start = samples[2];
|
||||
let fragment_pass_end = samples[3];
|
||||
|
||||
let cpu_time_span = cpu_end - cpu_start;
|
||||
let gpu_time_span = gpu_end - gpu_start;
|
||||
|
||||
let vertex_micros = microseconds_between_begin(
|
||||
vertex_pass_start,
|
||||
vertex_pass_end,
|
||||
gpu_time_span,
|
||||
cpu_time_span,
|
||||
);
|
||||
let fragment_micros = microseconds_between_begin(
|
||||
fragment_pass_start,
|
||||
fragment_pass_end,
|
||||
gpu_time_span,
|
||||
cpu_time_span,
|
||||
);
|
||||
|
||||
println!("Vertex pass duration: {:.2} µs", vertex_micros);
|
||||
println!("Fragment pass duration: {:.2} µs\n", fragment_micros);
|
||||
}
|
||||
|
||||
fn create_counter_sample_buffer(device: &Device) -> CounterSampleBuffer {
|
||||
let counter_sample_buffer_desc = metal::CounterSampleBufferDescriptor::new();
|
||||
counter_sample_buffer_desc.set_storage_mode(metal::MTLStorageMode::Shared);
|
||||
counter_sample_buffer_desc.set_sample_count(4_u64);
|
||||
counter_sample_buffer_desc.set_counter_set(&fetch_timestamp_counter_set(device));
|
||||
|
||||
device
|
||||
.new_counter_sample_buffer_with_descriptor(&counter_sample_buffer_desc)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn fetch_timestamp_counter_set(device: &Device) -> metal::CounterSet {
|
||||
let counter_sets = device.counter_sets();
|
||||
let mut timestamp_counter = None;
|
||||
for cs in counter_sets.iter() {
|
||||
if cs.name() == "timestamp" {
|
||||
timestamp_counter = Some(cs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
timestamp_counter
|
||||
.expect("No timestamp counter found")
|
||||
.clone()
|
||||
}
|
||||
|
||||
/// <https://developer.apple.com/documentation/metal/gpu_counters_and_counter_sample_buffers/converting_gpu_timestamps_into_cpu_time>
|
||||
fn microseconds_between_begin(begin: u64, end: u64, gpu_time_span: u64, cpu_time_span: u64) -> f64 {
|
||||
let time_span = (end as f64) - (begin as f64);
|
||||
let nanoseconds = time_span / (gpu_time_span as f64) * (cpu_time_span as f64);
|
||||
let microseconds = nanoseconds / 1000.0;
|
||||
return microseconds;
|
||||
}
|
||||
BIN
third-party/vendor/metal/examples/circle/screenshot.png
vendored
Normal file
BIN
third-party/vendor/metal/examples/circle/screenshot.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 468 KiB |
39
third-party/vendor/metal/examples/circle/shaders.metal
vendored
Normal file
39
third-party/vendor/metal/examples/circle/shaders.metal
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#include <metal_stdlib>
|
||||
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
}position;
|
||||
|
||||
typedef struct {
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
}color;
|
||||
|
||||
typedef struct {
|
||||
position p;
|
||||
color c;
|
||||
}AAPLVertex;
|
||||
|
||||
struct ColorInOut {
|
||||
float4 position[[position]];
|
||||
float4 color;
|
||||
};
|
||||
|
||||
vertex ColorInOut vs(constant AAPLVertex * vertex_array[[buffer(0)]], unsigned int vid[[vertex_id]]) {
|
||||
ColorInOut out;
|
||||
|
||||
out.position = float4(float2(vertex_array[vid].p.x, vertex_array[vid].p.y), 0.0, 1.0);
|
||||
out.color = float4(float3(vertex_array[vid].c.r, vertex_array[vid].c.g, vertex_array[vid].c.b), 1.0);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 ps(ColorInOut in [[stage_in]]) {
|
||||
return in.color;
|
||||
}
|
||||
BIN
third-party/vendor/metal/examples/circle/shaders.metallib
vendored
Normal file
BIN
third-party/vendor/metal/examples/circle/shaders.metallib
vendored
Normal file
Binary file not shown.
14
third-party/vendor/metal/examples/compute/compute-argument-buffer.metal
vendored
Normal file
14
third-party/vendor/metal/examples/compute/compute-argument-buffer.metal
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct SumInput {
|
||||
device uint *data;
|
||||
volatile device atomic_uint *sum;
|
||||
};
|
||||
|
||||
kernel void sum(device SumInput& input [[ buffer(0) ]],
|
||||
uint gid [[ thread_position_in_grid ]])
|
||||
{
|
||||
atomic_fetch_add_explicit(input.sum, input.data[gid], memory_order_relaxed);
|
||||
}
|
||||
95
third-party/vendor/metal/examples/compute/compute-argument-buffer.rs
vendored
Normal file
95
third-party/vendor/metal/examples/compute/compute-argument-buffer.rs
vendored
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
// Copyright 2017 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use metal::*;
|
||||
use objc::rc::autoreleasepool;
|
||||
use std::mem;
|
||||
|
||||
static LIBRARY_SRC: &str = include_str!("compute-argument-buffer.metal");
|
||||
|
||||
fn main() {
|
||||
autoreleasepool(|| {
|
||||
let device = Device::system_default().expect("no device found");
|
||||
let command_queue = device.new_command_queue();
|
||||
|
||||
let data = [
|
||||
1u32, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30,
|
||||
];
|
||||
|
||||
let buffer = device.new_buffer_with_data(
|
||||
unsafe { mem::transmute(data.as_ptr()) },
|
||||
(data.len() * mem::size_of::<u32>()) as u64,
|
||||
MTLResourceOptions::CPUCacheModeDefaultCache,
|
||||
);
|
||||
|
||||
let sum = {
|
||||
let data = [0u32];
|
||||
device.new_buffer_with_data(
|
||||
unsafe { mem::transmute(data.as_ptr()) },
|
||||
(data.len() * mem::size_of::<u32>()) as u64,
|
||||
MTLResourceOptions::CPUCacheModeDefaultCache,
|
||||
)
|
||||
};
|
||||
|
||||
let command_buffer = command_queue.new_command_buffer();
|
||||
let encoder = command_buffer.new_compute_command_encoder();
|
||||
|
||||
let library = device
|
||||
.new_library_with_source(LIBRARY_SRC, &CompileOptions::new())
|
||||
.unwrap();
|
||||
let kernel = library.get_function("sum", None).unwrap();
|
||||
|
||||
let argument_encoder = kernel.new_argument_encoder(0);
|
||||
let arg_buffer = device.new_buffer(
|
||||
argument_encoder.encoded_length(),
|
||||
MTLResourceOptions::empty(),
|
||||
);
|
||||
argument_encoder.set_argument_buffer(&arg_buffer, 0);
|
||||
argument_encoder.set_buffer(0, &buffer, 0);
|
||||
argument_encoder.set_buffer(1, &sum, 0);
|
||||
|
||||
let pipeline_state_descriptor = ComputePipelineDescriptor::new();
|
||||
pipeline_state_descriptor.set_compute_function(Some(&kernel));
|
||||
|
||||
let pipeline_state = device
|
||||
.new_compute_pipeline_state_with_function(
|
||||
pipeline_state_descriptor.compute_function().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
encoder.set_compute_pipeline_state(&pipeline_state);
|
||||
encoder.set_buffer(0, Some(&arg_buffer), 0);
|
||||
|
||||
encoder.use_resource(&buffer, MTLResourceUsage::Read);
|
||||
encoder.use_resource(&sum, MTLResourceUsage::Write);
|
||||
|
||||
let width = 16;
|
||||
|
||||
let thread_group_count = MTLSize {
|
||||
width,
|
||||
height: 1,
|
||||
depth: 1,
|
||||
};
|
||||
|
||||
let thread_group_size = MTLSize {
|
||||
width: (data.len() as u64 + width) / width,
|
||||
height: 1,
|
||||
depth: 1,
|
||||
};
|
||||
|
||||
encoder.dispatch_thread_groups(thread_group_count, thread_group_size);
|
||||
encoder.end_encoding();
|
||||
command_buffer.commit();
|
||||
command_buffer.wait_until_completed();
|
||||
|
||||
let ptr = sum.contents() as *mut u32;
|
||||
unsafe {
|
||||
assert_eq!(465, *ptr);
|
||||
}
|
||||
});
|
||||
}
|
||||
24
third-party/vendor/metal/examples/compute/embedded-lib.rs
vendored
Normal file
24
third-party/vendor/metal/examples/compute/embedded-lib.rs
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2017 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use metal::*;
|
||||
use objc::rc::autoreleasepool;
|
||||
|
||||
fn main() {
|
||||
let library_data = include_bytes!("shaders.metallib");
|
||||
|
||||
autoreleasepool(|| {
|
||||
let device = Device::system_default().expect("no device found");
|
||||
|
||||
let library = device.new_library_with_data(&library_data[..]).unwrap();
|
||||
let kernel = library.get_function("sum", None).unwrap();
|
||||
|
||||
println!("Function name: {}", kernel.name());
|
||||
println!("Function type: {:?}", kernel.function_type());
|
||||
println!("OK");
|
||||
});
|
||||
}
|
||||
194
third-party/vendor/metal/examples/compute/main.rs
vendored
Normal file
194
third-party/vendor/metal/examples/compute/main.rs
vendored
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
use metal::*;
|
||||
use objc::rc::autoreleasepool;
|
||||
use std::path::PathBuf;
|
||||
|
||||
const NUM_SAMPLES: u64 = 2;
|
||||
|
||||
fn main() {
|
||||
let num_elements = std::env::args()
|
||||
.nth(1)
|
||||
.map(|s| s.parse::<u32>().unwrap())
|
||||
.unwrap_or(64 * 64);
|
||||
|
||||
autoreleasepool(|| {
|
||||
let device = Device::system_default().expect("No device found");
|
||||
let mut cpu_start = 0;
|
||||
let mut gpu_start = 0;
|
||||
device.sample_timestamps(&mut cpu_start, &mut gpu_start);
|
||||
|
||||
let counter_sample_buffer = create_counter_sample_buffer(&device);
|
||||
let destination_buffer = device.new_buffer(
|
||||
(std::mem::size_of::<u64>() * NUM_SAMPLES as usize) as u64,
|
||||
MTLResourceOptions::StorageModeShared,
|
||||
);
|
||||
|
||||
let counter_sampling_point = MTLCounterSamplingPoint::AtStageBoundary;
|
||||
assert!(device.supports_counter_sampling(counter_sampling_point));
|
||||
|
||||
let command_queue = device.new_command_queue();
|
||||
let command_buffer = command_queue.new_command_buffer();
|
||||
|
||||
let compute_pass_descriptor = ComputePassDescriptor::new();
|
||||
handle_compute_pass_sample_buffer_attachment(
|
||||
compute_pass_descriptor,
|
||||
&counter_sample_buffer,
|
||||
);
|
||||
let encoder =
|
||||
command_buffer.compute_command_encoder_with_descriptor(compute_pass_descriptor);
|
||||
|
||||
let pipeline_state = create_pipeline_state(&device);
|
||||
encoder.set_compute_pipeline_state(&pipeline_state);
|
||||
|
||||
let (buffer, sum) = create_input_and_output_buffers(&device, num_elements);
|
||||
encoder.set_buffer(0, Some(&buffer), 0);
|
||||
encoder.set_buffer(1, Some(&sum), 0);
|
||||
|
||||
let num_threads = pipeline_state.thread_execution_width();
|
||||
|
||||
let thread_group_count = MTLSize {
|
||||
width: ((num_elements as NSUInteger + num_threads) / num_threads),
|
||||
height: 1,
|
||||
depth: 1,
|
||||
};
|
||||
|
||||
let thread_group_size = MTLSize {
|
||||
width: num_threads,
|
||||
height: 1,
|
||||
depth: 1,
|
||||
};
|
||||
|
||||
encoder.dispatch_thread_groups(thread_group_count, thread_group_size);
|
||||
encoder.end_encoding();
|
||||
|
||||
resolve_samples_into_buffer(command_buffer, &counter_sample_buffer, &destination_buffer);
|
||||
|
||||
command_buffer.commit();
|
||||
command_buffer.wait_until_completed();
|
||||
let mut cpu_end = 0;
|
||||
let mut gpu_end = 0;
|
||||
device.sample_timestamps(&mut cpu_end, &mut gpu_end);
|
||||
|
||||
let ptr = sum.contents() as *mut u32;
|
||||
println!("Compute shader sum: {}", unsafe { *ptr });
|
||||
|
||||
unsafe {
|
||||
assert_eq!(num_elements, *ptr);
|
||||
}
|
||||
|
||||
handle_timestamps(&destination_buffer, cpu_start, cpu_end, gpu_start, gpu_end);
|
||||
});
|
||||
}
|
||||
|
||||
fn create_pipeline_state(device: &Device) -> ComputePipelineState {
|
||||
let library_path =
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("examples/compute/shaders.metallib");
|
||||
let library = device.new_library_with_file(library_path).unwrap();
|
||||
let kernel = library.get_function("sum", None).unwrap();
|
||||
|
||||
let pipeline_state_descriptor = ComputePipelineDescriptor::new();
|
||||
pipeline_state_descriptor.set_compute_function(Some(&kernel));
|
||||
|
||||
device
|
||||
.new_compute_pipeline_state_with_function(
|
||||
pipeline_state_descriptor.compute_function().unwrap(),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn handle_compute_pass_sample_buffer_attachment(
|
||||
compute_pass_descriptor: &ComputePassDescriptorRef,
|
||||
counter_sample_buffer: &CounterSampleBufferRef,
|
||||
) {
|
||||
let sample_buffer_attachment_descriptor = compute_pass_descriptor
|
||||
.sample_buffer_attachments()
|
||||
.object_at(0)
|
||||
.unwrap();
|
||||
|
||||
sample_buffer_attachment_descriptor.set_sample_buffer(counter_sample_buffer);
|
||||
sample_buffer_attachment_descriptor.set_start_of_encoder_sample_index(0);
|
||||
sample_buffer_attachment_descriptor.set_end_of_encoder_sample_index(1);
|
||||
}
|
||||
|
||||
fn resolve_samples_into_buffer(
|
||||
command_buffer: &CommandBufferRef,
|
||||
counter_sample_buffer: &CounterSampleBufferRef,
|
||||
destination_buffer: &BufferRef,
|
||||
) {
|
||||
let blit_encoder = command_buffer.new_blit_command_encoder();
|
||||
blit_encoder.resolve_counters(
|
||||
counter_sample_buffer,
|
||||
crate::NSRange::new(0_u64, NUM_SAMPLES),
|
||||
destination_buffer,
|
||||
0_u64,
|
||||
);
|
||||
blit_encoder.end_encoding();
|
||||
}
|
||||
|
||||
fn handle_timestamps(
|
||||
resolved_sample_buffer: &BufferRef,
|
||||
cpu_start: u64,
|
||||
cpu_end: u64,
|
||||
gpu_start: u64,
|
||||
gpu_end: u64,
|
||||
) {
|
||||
let samples = unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
resolved_sample_buffer.contents() as *const u64,
|
||||
NUM_SAMPLES as usize,
|
||||
)
|
||||
};
|
||||
let pass_start = samples[0];
|
||||
let pass_end = samples[1];
|
||||
|
||||
let cpu_time_span = cpu_end - cpu_start;
|
||||
let gpu_time_span = gpu_end - gpu_start;
|
||||
|
||||
let micros = microseconds_between_begin(pass_start, pass_end, gpu_time_span, cpu_time_span);
|
||||
println!("Compute pass duration: {} µs", micros);
|
||||
}
|
||||
|
||||
fn create_counter_sample_buffer(device: &Device) -> CounterSampleBuffer {
|
||||
let counter_sample_buffer_desc = metal::CounterSampleBufferDescriptor::new();
|
||||
counter_sample_buffer_desc.set_storage_mode(metal::MTLStorageMode::Shared);
|
||||
counter_sample_buffer_desc.set_sample_count(NUM_SAMPLES);
|
||||
let counter_sets = device.counter_sets();
|
||||
|
||||
let timestamp_counter = counter_sets.iter().find(|cs| cs.name() == "timestamp");
|
||||
|
||||
counter_sample_buffer_desc
|
||||
.set_counter_set(timestamp_counter.expect("No timestamp counter found"));
|
||||
|
||||
device
|
||||
.new_counter_sample_buffer_with_descriptor(&counter_sample_buffer_desc)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn create_input_and_output_buffers(
|
||||
device: &Device,
|
||||
num_elements: u32,
|
||||
) -> (metal::Buffer, metal::Buffer) {
|
||||
let data = vec![1u32; num_elements as usize];
|
||||
|
||||
let buffer = device.new_buffer_with_data(
|
||||
unsafe { std::mem::transmute(data.as_ptr()) },
|
||||
(data.len() * std::mem::size_of::<u32>()) as u64,
|
||||
MTLResourceOptions::CPUCacheModeDefaultCache,
|
||||
);
|
||||
|
||||
let sum = {
|
||||
let data = [0u32];
|
||||
device.new_buffer_with_data(
|
||||
unsafe { std::mem::transmute(data.as_ptr()) },
|
||||
(data.len() * std::mem::size_of::<u32>()) as u64,
|
||||
MTLResourceOptions::CPUCacheModeDefaultCache,
|
||||
)
|
||||
};
|
||||
(buffer, sum)
|
||||
}
|
||||
|
||||
/// <https://developer.apple.com/documentation/metal/gpu_counters_and_counter_sample_buffers/converting_gpu_timestamps_into_cpu_time>
|
||||
fn microseconds_between_begin(begin: u64, end: u64, gpu_time_span: u64, cpu_time_span: u64) -> f64 {
|
||||
let time_span = (end as f64) - (begin as f64);
|
||||
let nanoseconds = time_span / (gpu_time_span as f64) * (cpu_time_span as f64);
|
||||
nanoseconds / 1000.0
|
||||
}
|
||||
10
third-party/vendor/metal/examples/compute/shaders.metal
vendored
Normal file
10
third-party/vendor/metal/examples/compute/shaders.metal
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
kernel void sum(device uint *data [[ buffer(0) ]],
|
||||
volatile device atomic_uint *sum [[ buffer(1) ]],
|
||||
uint gid [[ thread_position_in_grid ]])
|
||||
{
|
||||
atomic_fetch_add_explicit(sum, data[gid], memory_order_relaxed);
|
||||
}
|
||||
BIN
third-party/vendor/metal/examples/compute/shaders.metallib
vendored
Normal file
BIN
third-party/vendor/metal/examples/compute/shaders.metallib
vendored
Normal file
Binary file not shown.
50
third-party/vendor/metal/examples/events/main.rs
vendored
Normal file
50
third-party/vendor/metal/examples/events/main.rs
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2020 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use dispatch::{Queue, QueueAttribute};
|
||||
use metal::*;
|
||||
|
||||
/// This example replicates `Synchronizing Events Between a GPU and the CPU` article.
|
||||
/// See https://developer.apple.com/documentation/metal/synchronization/synchronizing_events_between_a_gpu_and_the_cpu
|
||||
fn main() {
|
||||
let device = Device::system_default().expect("No device found");
|
||||
|
||||
let command_queue = device.new_command_queue();
|
||||
let command_buffer = command_queue.new_command_buffer();
|
||||
|
||||
// Shareable event
|
||||
let shared_event = device.new_shared_event();
|
||||
|
||||
// Shareable event listener
|
||||
let my_queue = Queue::create(
|
||||
"com.example.apple-samplecode.MyQueue",
|
||||
QueueAttribute::Serial,
|
||||
);
|
||||
|
||||
// Enable `dispatch` feature to use dispatch queues,
|
||||
// otherwise unsafe `from_queue_handle` is available for use with native APIs.
|
||||
let shared_event_listener = SharedEventListener::from_queue(&my_queue);
|
||||
|
||||
// Register CPU work
|
||||
let notify_block = block::ConcreteBlock::new(move |evt: &SharedEventRef, val: u64| {
|
||||
println!("Got notification from GPU: {}", val);
|
||||
evt.set_signaled_value(3);
|
||||
});
|
||||
|
||||
shared_event.notify(&shared_event_listener, 2, notify_block.copy());
|
||||
|
||||
// Encode GPU work
|
||||
command_buffer.encode_signal_event(&shared_event, 1);
|
||||
command_buffer.encode_signal_event(&shared_event, 2);
|
||||
command_buffer.encode_wait_for_event(&shared_event, 3);
|
||||
|
||||
command_buffer.commit();
|
||||
|
||||
command_buffer.wait_until_completed();
|
||||
|
||||
println!("Done");
|
||||
}
|
||||
30
third-party/vendor/metal/examples/fence/main.rs
vendored
Normal file
30
third-party/vendor/metal/examples/fence/main.rs
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2020 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use metal::*;
|
||||
|
||||
fn main() {
|
||||
let device = Device::system_default().expect("No device found");
|
||||
|
||||
let command_queue = device.new_command_queue();
|
||||
let command_buffer = command_queue.new_command_buffer();
|
||||
|
||||
let fence = device.new_fence();
|
||||
|
||||
let blit_encoder = command_buffer.new_blit_command_encoder();
|
||||
blit_encoder.update_fence(&fence);
|
||||
blit_encoder.end_encoding();
|
||||
|
||||
let compute_encoder = command_buffer.new_compute_command_encoder();
|
||||
compute_encoder.wait_for_fence(&fence);
|
||||
compute_encoder.end_encoding();
|
||||
|
||||
command_buffer.commit();
|
||||
command_buffer.wait_until_completed();
|
||||
|
||||
println!("Done");
|
||||
}
|
||||
11
third-party/vendor/metal/examples/headless-render/README.md
vendored
Normal file
11
third-party/vendor/metal/examples/headless-render/README.md
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
## headless-render
|
||||
|
||||
Renders the triangle from the [window example](../window) headlessly and then writes it to a PNG file.
|
||||
|
||||

|
||||
|
||||
## To Run
|
||||
|
||||
```
|
||||
cargo run --example headless-render
|
||||
```
|
||||
159
third-party/vendor/metal/examples/headless-render/main.rs
vendored
Normal file
159
third-party/vendor/metal/examples/headless-render/main.rs
vendored
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
use std::mem;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::BufWriter;
|
||||
|
||||
use metal::{
|
||||
Buffer, Device, DeviceRef, LibraryRef, MTLClearColor, MTLLoadAction, MTLOrigin, MTLPixelFormat,
|
||||
MTLPrimitiveType, MTLRegion, MTLResourceOptions, MTLSize, MTLStoreAction, RenderPassDescriptor,
|
||||
RenderPassDescriptorRef, RenderPipelineDescriptor, RenderPipelineState, Texture,
|
||||
TextureDescriptor, TextureRef,
|
||||
};
|
||||
use png::ColorType;
|
||||
|
||||
const VIEW_WIDTH: u64 = 512;
|
||||
const VIEW_HEIGHT: u64 = 512;
|
||||
const TOTAL_BYTES: usize = (VIEW_WIDTH * VIEW_HEIGHT * 4) as usize;
|
||||
|
||||
const VERTEX_SHADER: &'static str = "triangle_vertex";
|
||||
const FRAGMENT_SHADER: &'static str = "triangle_fragment";
|
||||
|
||||
// [2 bytes position, 3 bytes color] * 3
|
||||
#[rustfmt::skip]
|
||||
const VERTEX_ATTRIBS: [f32; 15] = [
|
||||
0.0, 0.5, 1.0, 0.0, 0.0,
|
||||
-0.5, -0.5, 0.0, 1.0, 0.0,
|
||||
0.5, -0.5, 0.0, 0.0, 1.0,
|
||||
];
|
||||
|
||||
/// This example shows how to render headlessly by:
|
||||
///
|
||||
/// 1. Rendering a triangle to an MtlDrawable
|
||||
///
|
||||
/// 2. Waiting for the render to complete and the color texture to be synchronized with the CPU
|
||||
/// by using a blit command encoder
|
||||
///
|
||||
/// 3. Reading the texture bytes from the MtlTexture
|
||||
///
|
||||
/// 4. Saving the texture to a PNG file
|
||||
fn main() {
|
||||
let device = Device::system_default().expect("No device found");
|
||||
|
||||
let texture = create_texture(&device);
|
||||
|
||||
let library_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("examples/window/shaders.metallib");
|
||||
|
||||
let library = device.new_library_with_file(library_path).unwrap();
|
||||
|
||||
let pipeline_state = prepare_pipeline_state(&device, &library);
|
||||
|
||||
let command_queue = device.new_command_queue();
|
||||
|
||||
let vertex_buffer = create_vertex_buffer(&device);
|
||||
|
||||
let render_pass_descriptor = RenderPassDescriptor::new();
|
||||
initialize_color_attachment(&render_pass_descriptor, &texture);
|
||||
|
||||
let command_buffer = command_queue.new_command_buffer();
|
||||
let rc_encoder = command_buffer.new_render_command_encoder(&render_pass_descriptor);
|
||||
rc_encoder.set_render_pipeline_state(&pipeline_state);
|
||||
rc_encoder.set_vertex_buffer(0, Some(&vertex_buffer), 0);
|
||||
rc_encoder.draw_primitives(MTLPrimitiveType::Triangle, 0, 3);
|
||||
rc_encoder.end_encoding();
|
||||
|
||||
render_pass_descriptor
|
||||
.color_attachments()
|
||||
.object_at(0)
|
||||
.unwrap()
|
||||
.set_load_action(MTLLoadAction::DontCare);
|
||||
|
||||
let blit_encoder = command_buffer.new_blit_command_encoder();
|
||||
blit_encoder.synchronize_resource(&texture);
|
||||
blit_encoder.end_encoding();
|
||||
|
||||
command_buffer.commit();
|
||||
|
||||
command_buffer.wait_until_completed();
|
||||
|
||||
save_image(&texture);
|
||||
}
|
||||
|
||||
fn save_image(texture: &TextureRef) {
|
||||
let mut image = vec![0; TOTAL_BYTES];
|
||||
|
||||
texture.get_bytes(
|
||||
image.as_mut_ptr() as *mut std::ffi::c_void,
|
||||
VIEW_WIDTH * 4,
|
||||
MTLRegion {
|
||||
origin: MTLOrigin { x: 0, y: 0, z: 0 },
|
||||
size: MTLSize {
|
||||
width: VIEW_WIDTH,
|
||||
height: VIEW_HEIGHT,
|
||||
depth: 1,
|
||||
},
|
||||
},
|
||||
0,
|
||||
);
|
||||
|
||||
let out_file =
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("examples/headless-render/out.png");
|
||||
let file = File::create(&out_file).unwrap();
|
||||
let ref mut w = BufWriter::new(file);
|
||||
|
||||
let mut encoder = png::Encoder::new(w, VIEW_WIDTH as u32, VIEW_HEIGHT as u32);
|
||||
encoder.set_color(ColorType::Rgba);
|
||||
encoder.set_depth(png::BitDepth::Eight);
|
||||
let mut writer = encoder.write_header().unwrap();
|
||||
|
||||
writer.write_image_data(&image).unwrap();
|
||||
|
||||
println!("Image saved to {:?}", out_file);
|
||||
}
|
||||
|
||||
fn create_texture(device: &Device) -> Texture {
|
||||
let texture = TextureDescriptor::new();
|
||||
texture.set_width(VIEW_WIDTH);
|
||||
texture.set_height(VIEW_HEIGHT);
|
||||
texture.set_pixel_format(MTLPixelFormat::RGBA8Unorm);
|
||||
|
||||
device.new_texture(&texture)
|
||||
}
|
||||
|
||||
fn prepare_pipeline_state(device: &DeviceRef, library: &LibraryRef) -> RenderPipelineState {
|
||||
let vert = library.get_function(VERTEX_SHADER, None).unwrap();
|
||||
let frag = library.get_function(FRAGMENT_SHADER, None).unwrap();
|
||||
|
||||
let pipeline_state_descriptor = RenderPipelineDescriptor::new();
|
||||
|
||||
pipeline_state_descriptor.set_vertex_function(Some(&vert));
|
||||
pipeline_state_descriptor.set_fragment_function(Some(&frag));
|
||||
|
||||
pipeline_state_descriptor
|
||||
.color_attachments()
|
||||
.object_at(0)
|
||||
.unwrap()
|
||||
.set_pixel_format(MTLPixelFormat::RGBA8Unorm);
|
||||
|
||||
device
|
||||
.new_render_pipeline_state(&pipeline_state_descriptor)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn create_vertex_buffer(device: &DeviceRef) -> Buffer {
|
||||
device.new_buffer_with_data(
|
||||
VERTEX_ATTRIBS.as_ptr() as *const _,
|
||||
(VERTEX_ATTRIBS.len() * mem::size_of::<f32>()) as u64,
|
||||
MTLResourceOptions::CPUCacheModeDefaultCache | MTLResourceOptions::StorageModeManaged,
|
||||
)
|
||||
}
|
||||
|
||||
fn initialize_color_attachment(descriptor: &RenderPassDescriptorRef, texture: &TextureRef) {
|
||||
let color_attachment = descriptor.color_attachments().object_at(0).unwrap();
|
||||
|
||||
color_attachment.set_texture(Some(texture));
|
||||
color_attachment.set_load_action(MTLLoadAction::Clear);
|
||||
color_attachment.set_clear_color(MTLClearColor::new(0.5, 0.2, 0.2, 1.0));
|
||||
color_attachment.set_store_action(MTLStoreAction::Store);
|
||||
}
|
||||
BIN
third-party/vendor/metal/examples/headless-render/screenshot.png
vendored
Normal file
BIN
third-party/vendor/metal/examples/headless-render/screenshot.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
17
third-party/vendor/metal/examples/library/main.rs
vendored
Normal file
17
third-party/vendor/metal/examples/library/main.rs
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use metal::*;
|
||||
|
||||
const PROGRAM: &'static str = "";
|
||||
|
||||
fn main() {
|
||||
let device = Device::system_default().expect("no device found");
|
||||
|
||||
let options = CompileOptions::new();
|
||||
let _library = device.new_library_with_source(PROGRAM, &options);
|
||||
}
|
||||
118
third-party/vendor/metal/examples/mesh-shader/main.rs
vendored
Normal file
118
third-party/vendor/metal/examples/mesh-shader/main.rs
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
extern crate objc;
|
||||
|
||||
use cocoa::{appkit::NSView, base::id as cocoa_id};
|
||||
use core_graphics_types::geometry::CGSize;
|
||||
|
||||
use metal::*;
|
||||
use objc::{rc::autoreleasepool, runtime::YES};
|
||||
use std::mem;
|
||||
use winit::platform::macos::WindowExtMacOS;
|
||||
|
||||
use winit::{
|
||||
event::{Event, WindowEvent},
|
||||
event_loop::ControlFlow,
|
||||
};
|
||||
|
||||
fn prepare_render_pass_descriptor(descriptor: &RenderPassDescriptorRef, texture: &TextureRef) {
|
||||
let color_attachment = descriptor.color_attachments().object_at(0).unwrap();
|
||||
|
||||
color_attachment.set_texture(Some(texture));
|
||||
color_attachment.set_load_action(MTLLoadAction::Clear);
|
||||
color_attachment.set_clear_color(MTLClearColor::new(0.2, 0.2, 0.25, 1.0));
|
||||
color_attachment.set_store_action(MTLStoreAction::Store);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let events_loop = winit::event_loop::EventLoop::new();
|
||||
let size = winit::dpi::LogicalSize::new(800, 600);
|
||||
|
||||
let window = winit::window::WindowBuilder::new()
|
||||
.with_inner_size(size)
|
||||
.with_title("Metal Mesh Shader Example".to_string())
|
||||
.build(&events_loop)
|
||||
.unwrap();
|
||||
|
||||
let device = Device::system_default().expect("no device found");
|
||||
|
||||
let layer = MetalLayer::new();
|
||||
layer.set_device(&device);
|
||||
layer.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
|
||||
layer.set_presents_with_transaction(false);
|
||||
|
||||
unsafe {
|
||||
let view = window.ns_view() as cocoa_id;
|
||||
view.setWantsLayer(YES);
|
||||
view.setLayer(mem::transmute(layer.as_ref()));
|
||||
}
|
||||
|
||||
let draw_size = window.inner_size();
|
||||
layer.set_drawable_size(CGSize::new(draw_size.width as f64, draw_size.height as f64));
|
||||
|
||||
let library_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("examples/mesh-shader/shaders.metallib");
|
||||
let library = device.new_library_with_file(library_path).unwrap();
|
||||
|
||||
let mesh = library.get_function("mesh_function", None).unwrap();
|
||||
let frag = library.get_function("fragment_function", None).unwrap();
|
||||
|
||||
let pipeline_state_desc = MeshRenderPipelineDescriptor::new();
|
||||
pipeline_state_desc
|
||||
.color_attachments()
|
||||
.object_at(0)
|
||||
.unwrap()
|
||||
.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
|
||||
pipeline_state_desc.set_mesh_function(Some(&mesh));
|
||||
pipeline_state_desc.set_fragment_function(Some(&frag));
|
||||
|
||||
let pipeline_state = device
|
||||
.new_mesh_render_pipeline_state(&pipeline_state_desc)
|
||||
.unwrap();
|
||||
|
||||
let command_queue = device.new_command_queue();
|
||||
|
||||
events_loop.run(move |event, _, control_flow| {
|
||||
autoreleasepool(|| {
|
||||
*control_flow = ControlFlow::Poll;
|
||||
|
||||
match event {
|
||||
Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
||||
WindowEvent::Resized(size) => {
|
||||
layer.set_drawable_size(CGSize::new(size.width as f64, size.height as f64));
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
Event::MainEventsCleared => {
|
||||
window.request_redraw();
|
||||
}
|
||||
Event::RedrawRequested(_) => {
|
||||
let drawable = match layer.next_drawable() {
|
||||
Some(drawable) => drawable,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let render_pass_descriptor = RenderPassDescriptor::new();
|
||||
|
||||
prepare_render_pass_descriptor(&render_pass_descriptor, drawable.texture());
|
||||
|
||||
let command_buffer = command_queue.new_command_buffer();
|
||||
let encoder =
|
||||
command_buffer.new_render_command_encoder(&render_pass_descriptor);
|
||||
|
||||
encoder.set_render_pipeline_state(&pipeline_state);
|
||||
encoder.draw_mesh_threads(
|
||||
MTLSize::new(1, 1, 1),
|
||||
MTLSize::new(1, 1, 1),
|
||||
MTLSize::new(1, 1, 1),
|
||||
);
|
||||
|
||||
encoder.end_encoding();
|
||||
|
||||
command_buffer.present_drawable(&drawable);
|
||||
command_buffer.commit();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
30
third-party/vendor/metal/examples/mesh-shader/shaders.metal
vendored
Normal file
30
third-party/vendor/metal/examples/mesh-shader/shaders.metal
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct VertexOut {
|
||||
float4 position [[position]];
|
||||
};
|
||||
|
||||
using mesh_t = mesh<VertexOut, void, 3, 1, topology::triangle>;
|
||||
|
||||
[[mesh]] void mesh_function(mesh_t m) {
|
||||
VertexOut v;
|
||||
v.position = float4(-1.0, -1.0, 0.0, 1.0);
|
||||
|
||||
m.set_primitive_count(1);
|
||||
|
||||
m.set_vertex(0, v);
|
||||
v.position = float4(0.0, 1.0, 0.0, 1.0);
|
||||
m.set_vertex(1, v);
|
||||
v.position = float4(1.0, -1.0, 0.0, 1.0);
|
||||
m.set_vertex(2, v);
|
||||
|
||||
m.set_index(0, 0);
|
||||
m.set_index(1, 1);
|
||||
m.set_index(2, 2);
|
||||
}
|
||||
|
||||
fragment half4 fragment_function() {
|
||||
return half4(0.1, 1.0, 0.1, 1.0);
|
||||
}
|
||||
BIN
third-party/vendor/metal/examples/mesh-shader/shaders.metallib
vendored
Normal file
BIN
third-party/vendor/metal/examples/mesh-shader/shaders.metallib
vendored
Normal file
Binary file not shown.
148
third-party/vendor/metal/examples/mps/main.rs
vendored
Normal file
148
third-party/vendor/metal/examples/mps/main.rs
vendored
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
use metal::*;
|
||||
use std::ffi::c_void;
|
||||
use std::mem;
|
||||
|
||||
#[repr(C)]
|
||||
struct Vertex {
|
||||
xyz: [f32; 3],
|
||||
}
|
||||
|
||||
type Ray = mps::MPSRayOriginMinDistanceDirectionMaxDistance;
|
||||
type Intersection = mps::MPSIntersectionDistancePrimitiveIndexCoordinates;
|
||||
|
||||
// Original example taken from https://sergeyreznik.github.io/metal-ray-tracer/part-1/index.html
|
||||
fn main() {
|
||||
let device = Device::system_default().expect("No device found");
|
||||
|
||||
let library_path =
|
||||
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("examples/mps/shaders.metallib");
|
||||
let library = device
|
||||
.new_library_with_file(library_path)
|
||||
.expect("Failed to load shader library");
|
||||
|
||||
let generate_rays_pipeline = create_pipeline("generateRays", &library, &device);
|
||||
|
||||
let queue = device.new_command_queue();
|
||||
let command_buffer = queue.new_command_buffer();
|
||||
|
||||
// Simple vertex/index buffer data
|
||||
|
||||
let vertices: [Vertex; 3] = [
|
||||
Vertex {
|
||||
xyz: [0.25, 0.25, 0.0],
|
||||
},
|
||||
Vertex {
|
||||
xyz: [0.75, 0.25, 0.0],
|
||||
},
|
||||
Vertex {
|
||||
xyz: [0.50, 0.75, 0.0],
|
||||
},
|
||||
];
|
||||
|
||||
let vertex_stride = mem::size_of::<Vertex>();
|
||||
|
||||
let indices: [u32; 3] = [0, 1, 2];
|
||||
|
||||
// Vertex data should be stored in private or managed buffers on discrete GPU systems (AMD, NVIDIA).
|
||||
// Private buffers are stored entirely in GPU memory and cannot be accessed by the CPU. Managed
|
||||
// buffers maintain a copy in CPU memory and a copy in GPU memory.
|
||||
let buffer_opts = MTLResourceOptions::StorageModeManaged;
|
||||
|
||||
let vertex_buffer = device.new_buffer_with_data(
|
||||
vertices.as_ptr() as *const c_void,
|
||||
(vertex_stride * vertices.len()) as u64,
|
||||
buffer_opts,
|
||||
);
|
||||
|
||||
let index_buffer = device.new_buffer_with_data(
|
||||
indices.as_ptr() as *const c_void,
|
||||
(mem::size_of::<u32>() * indices.len()) as u64,
|
||||
buffer_opts,
|
||||
);
|
||||
|
||||
// Build an acceleration structure using our vertex and index buffers containing the single triangle.
|
||||
let acceleration_structure = mps::TriangleAccelerationStructure::from_device(&device)
|
||||
.expect("Failed to create acceleration structure");
|
||||
|
||||
acceleration_structure.set_vertex_buffer(Some(&vertex_buffer));
|
||||
acceleration_structure.set_vertex_stride(vertex_stride as u64);
|
||||
acceleration_structure.set_index_buffer(Some(&index_buffer));
|
||||
acceleration_structure.set_index_type(mps::MPSDataType::UInt32);
|
||||
acceleration_structure.set_triangle_count(1);
|
||||
acceleration_structure.set_usage(mps::MPSAccelerationStructureUsage::None);
|
||||
acceleration_structure.rebuild();
|
||||
|
||||
let ray_intersector =
|
||||
mps::RayIntersector::from_device(&device).expect("Failed to create ray intersector");
|
||||
|
||||
ray_intersector.set_ray_stride(mem::size_of::<Ray>() as u64);
|
||||
ray_intersector.set_ray_data_type(mps::MPSRayDataType::OriginMinDistanceDirectionMaxDistance);
|
||||
ray_intersector.set_intersection_stride(mem::size_of::<Intersection>() as u64);
|
||||
ray_intersector.set_intersection_data_type(
|
||||
mps::MPSIntersectionDataType::DistancePrimitiveIndexCoordinates,
|
||||
);
|
||||
|
||||
// Create a buffer to hold generated rays and intersection results
|
||||
let ray_count = 1024;
|
||||
let ray_buffer = device.new_buffer(
|
||||
(mem::size_of::<Ray>() * ray_count) as u64,
|
||||
MTLResourceOptions::StorageModePrivate,
|
||||
);
|
||||
|
||||
let intersection_buffer = device.new_buffer(
|
||||
(mem::size_of::<Intersection>() * ray_count) as u64,
|
||||
MTLResourceOptions::StorageModePrivate,
|
||||
);
|
||||
|
||||
// Run the compute shader to generate rays
|
||||
let encoder = command_buffer.new_compute_command_encoder();
|
||||
encoder.set_buffer(0, Some(&ray_buffer), 0);
|
||||
encoder.set_compute_pipeline_state(&generate_rays_pipeline);
|
||||
encoder.dispatch_thread_groups(
|
||||
MTLSize {
|
||||
width: 4,
|
||||
height: 4,
|
||||
depth: 1,
|
||||
},
|
||||
MTLSize {
|
||||
width: 8,
|
||||
height: 8,
|
||||
depth: 1,
|
||||
},
|
||||
);
|
||||
encoder.end_encoding();
|
||||
|
||||
// Intersect rays with triangles inside acceleration structure
|
||||
ray_intersector.encode_intersection_to_command_buffer(
|
||||
&command_buffer,
|
||||
mps::MPSIntersectionType::Nearest,
|
||||
&ray_buffer,
|
||||
0,
|
||||
&intersection_buffer,
|
||||
0,
|
||||
ray_count as u64,
|
||||
&acceleration_structure,
|
||||
);
|
||||
|
||||
command_buffer.commit();
|
||||
command_buffer.wait_until_completed();
|
||||
|
||||
println!("Done");
|
||||
}
|
||||
|
||||
fn create_pipeline(func: &str, library: &LibraryRef, device: &DeviceRef) -> ComputePipelineState {
|
||||
// Create compute pipelines will will execute code on the GPU
|
||||
let compute_descriptor = ComputePipelineDescriptor::new();
|
||||
|
||||
// Set to YES to allow compiler to make certain optimizations
|
||||
compute_descriptor.set_thread_group_size_is_multiple_of_thread_execution_width(true);
|
||||
|
||||
let function = library.get_function(func, None).unwrap();
|
||||
compute_descriptor.set_compute_function(Some(&function));
|
||||
|
||||
let pipeline = device
|
||||
.new_compute_pipeline_state(&compute_descriptor)
|
||||
.unwrap();
|
||||
|
||||
pipeline
|
||||
}
|
||||
26
third-party/vendor/metal/examples/mps/shaders.metal
vendored
Normal file
26
third-party/vendor/metal/examples/mps/shaders.metal
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// Created by Sergey Reznik on 9/15/18.
|
||||
// Copyright © 2018 Serhii Rieznik. All rights reserved.
|
||||
//
|
||||
|
||||
// Taken from https://github.com/sergeyreznik/metal-ray-tracer/tree/part-1/source/Shaders
|
||||
// MIT License https://github.com/sergeyreznik/metal-ray-tracer/blob/part-1/LICENSE
|
||||
|
||||
#include <MetalPerformanceShaders/MetalPerformanceShaders.h>
|
||||
|
||||
using Ray = MPSRayOriginMinDistanceDirectionMaxDistance;
|
||||
using Intersection = MPSIntersectionDistancePrimitiveIndexCoordinates;
|
||||
|
||||
kernel void generateRays(
|
||||
device Ray* rays [[buffer(0)]],
|
||||
uint2 coordinates [[thread_position_in_grid]],
|
||||
uint2 size [[threads_per_grid]])
|
||||
{
|
||||
float2 uv = float2(coordinates) / float2(size - 1);
|
||||
|
||||
uint rayIndex = coordinates.x + coordinates.y * size.x;
|
||||
rays[rayIndex].origin = MPSPackedFloat3(uv.x, uv.y, -1.0);
|
||||
rays[rayIndex].direction = MPSPackedFloat3(0.0, 0.0, 1.0);
|
||||
rays[rayIndex].minDistance = 0.0f;
|
||||
rays[rayIndex].maxDistance = 2.0f;
|
||||
}
|
||||
BIN
third-party/vendor/metal/examples/mps/shaders.metallib
vendored
Normal file
BIN
third-party/vendor/metal/examples/mps/shaders.metallib
vendored
Normal file
Binary file not shown.
11
third-party/vendor/metal/examples/raytracing/README.md
vendored
Normal file
11
third-party/vendor/metal/examples/raytracing/README.md
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
## Raytracing
|
||||
|
||||
A good showcase of Metal 3 raytracing features.
|
||||
|
||||

|
||||
|
||||
## To Run
|
||||
|
||||
```
|
||||
cargo run --example raytracing
|
||||
```
|
||||
20
third-party/vendor/metal/examples/raytracing/camera.rs
vendored
Normal file
20
third-party/vendor/metal/examples/raytracing/camera.rs
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
use glam::f32::Vec4;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Camera {
|
||||
pub position: Vec4,
|
||||
pub right: Vec4,
|
||||
pub up: Vec4,
|
||||
pub forward: Vec4,
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
position: Vec4::new(0.0, 3.0, 10.0, 0.0),
|
||||
right: Vec4::new(1.0, 0.0, 0.0, 0.0),
|
||||
up: Vec4::new(0.0, 1.0, 0.0, 0.0),
|
||||
forward: Vec4::new(0.0, 0.0, -1.0, 0.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
448
third-party/vendor/metal/examples/raytracing/geometry.rs
vendored
Normal file
448
third-party/vendor/metal/examples/raytracing/geometry.rs
vendored
Normal file
|
|
@ -0,0 +1,448 @@
|
|||
use std::{
|
||||
mem::{size_of, transmute},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use glam::{
|
||||
f32::{Mat4, Vec3, Vec4},
|
||||
Vec4Swizzles,
|
||||
};
|
||||
|
||||
use metal::*;
|
||||
|
||||
pub const GEOMETRY_MASK_TRIANGLE: u32 = 1;
|
||||
pub const GEOMETRY_MASK_SPHERE: u32 = 2;
|
||||
pub const GEOMETRY_MASK_LIGHT: u32 = 4;
|
||||
|
||||
pub const FACE_MASK_NONE: u16 = 0;
|
||||
pub const FACE_MASK_NEGATIVE_X: u16 = 1 << 0;
|
||||
pub const FACE_MASK_POSITIVE_X: u16 = 1 << 1;
|
||||
pub const FACE_MASK_NEGATIVE_Y: u16 = 1 << 2;
|
||||
pub const FACE_MASK_POSITIVE_Y: u16 = 1 << 3;
|
||||
pub const FACE_MASK_NEGATIVE_Z: u16 = 1 << 4;
|
||||
pub const FACE_MASK_POSITIVE_Z: u16 = 1 << 5;
|
||||
pub const FACE_MASK_ALL: u16 = (1 << 6) - 1;
|
||||
|
||||
pub trait Geometry {
|
||||
fn upload_to_buffers(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
fn clear(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
fn get_geometry_descriptor(&self) -> AccelerationStructureGeometryDescriptor {
|
||||
todo!()
|
||||
}
|
||||
fn get_resources(&self) -> Vec<Resource> {
|
||||
todo!()
|
||||
}
|
||||
fn get_intersection_function_name(&self) -> Option<&str> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_triangle_normal(v0: &Vec3, v1: &Vec3, v2: &Vec3) -> Vec3 {
|
||||
let e1 = Vec3::normalize(*v1 - *v0);
|
||||
let e2 = Vec3::normalize(*v2 - *v0);
|
||||
return Vec3::cross(e1, e2);
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[repr(C)]
|
||||
pub struct Triangle {
|
||||
pub normals: [Vec4; 3],
|
||||
pub colours: [Vec4; 3],
|
||||
}
|
||||
|
||||
pub fn get_managed_buffer_storage_mode() -> MTLResourceOptions {
|
||||
return MTLResourceOptions::StorageModeManaged;
|
||||
}
|
||||
|
||||
pub struct TriangleGeometry {
|
||||
pub device: Device,
|
||||
pub name: String,
|
||||
pub index_buffer: Option<Buffer>,
|
||||
pub vertex_position_buffer: Option<Buffer>,
|
||||
pub vertex_normal_buffer: Option<Buffer>,
|
||||
pub vertex_colour_buffer: Option<Buffer>,
|
||||
pub per_primitive_data_buffer: Option<Buffer>,
|
||||
pub indices: Vec<u16>,
|
||||
pub vertices: Vec<Vec4>,
|
||||
pub normals: Vec<Vec4>,
|
||||
pub colours: Vec<Vec4>,
|
||||
pub triangles: Vec<Triangle>,
|
||||
}
|
||||
|
||||
impl TriangleGeometry {
|
||||
pub fn new(device: Device, name: String) -> Self {
|
||||
Self {
|
||||
device,
|
||||
name,
|
||||
index_buffer: None,
|
||||
vertex_position_buffer: None,
|
||||
vertex_normal_buffer: None,
|
||||
vertex_colour_buffer: None,
|
||||
per_primitive_data_buffer: None,
|
||||
indices: Vec::new(),
|
||||
vertices: Vec::new(),
|
||||
normals: Vec::new(),
|
||||
colours: Vec::new(),
|
||||
triangles: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_cube_face_with_cube_vertices(
|
||||
&mut self,
|
||||
cube_vertices: &[Vec3],
|
||||
colour: Vec3,
|
||||
i0: u16,
|
||||
i1: u16,
|
||||
i2: u16,
|
||||
i3: u16,
|
||||
inward_normals: bool,
|
||||
) {
|
||||
let v0 = cube_vertices[i0 as usize];
|
||||
let v1 = cube_vertices[i1 as usize];
|
||||
let v2 = cube_vertices[i2 as usize];
|
||||
let v3 = cube_vertices[i3 as usize];
|
||||
|
||||
let n0 = compute_triangle_normal(&v0, &v1, &v2) * if inward_normals { -1f32 } else { 1f32 };
|
||||
let n1 = compute_triangle_normal(&v0, &v2, &v3) * if inward_normals { -1f32 } else { 1f32 };
|
||||
|
||||
let first_index = self.indices.len();
|
||||
let base_index = self.vertices.len() as u16;
|
||||
|
||||
self.indices.push(base_index + 0);
|
||||
self.indices.push(base_index + 1);
|
||||
self.indices.push(base_index + 2);
|
||||
self.indices.push(base_index + 0);
|
||||
self.indices.push(base_index + 2);
|
||||
self.indices.push(base_index + 3);
|
||||
|
||||
self.vertices.push(From::from((v0, 0.0)));
|
||||
self.vertices.push(From::from((v1, 0.0)));
|
||||
self.vertices.push(From::from((v2, 0.0)));
|
||||
self.vertices.push(From::from((v3, 0.0)));
|
||||
|
||||
self.normals
|
||||
.push(From::from((Vec3::normalize(n0 + n1), 0.0)));
|
||||
self.normals.push(From::from((n0, 0.0)));
|
||||
self.normals
|
||||
.push(From::from((Vec3::normalize(n0 + n1), 0.0)));
|
||||
self.normals.push(From::from((n1, 0.0)));
|
||||
|
||||
for _ in 0..4 {
|
||||
self.colours.push(From::from((colour, 0.0)));
|
||||
}
|
||||
|
||||
for triangle_index in 0..2 {
|
||||
let mut triangle = Triangle::default();
|
||||
for i in 0..3 {
|
||||
let index = self.indices[first_index + triangle_index * 3 + i];
|
||||
triangle.normals[i] = self.normals[index as usize];
|
||||
triangle.colours[i] = self.colours[index as usize];
|
||||
}
|
||||
self.triangles.push(triangle);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_cube_with_faces(
|
||||
&mut self,
|
||||
face_mask: u16,
|
||||
colour: Vec3,
|
||||
transform: Mat4,
|
||||
inward_normals: bool,
|
||||
) {
|
||||
let mut cube_vertices = [
|
||||
Vec3::new(-0.5, -0.5, -0.5),
|
||||
Vec3::new(0.5, -0.5, -0.5),
|
||||
Vec3::new(-0.5, 0.5, -0.5),
|
||||
Vec3::new(0.5, 0.5, -0.5),
|
||||
Vec3::new(-0.5, -0.5, 0.5),
|
||||
Vec3::new(0.5, -0.5, 0.5),
|
||||
Vec3::new(-0.5, 0.5, 0.5),
|
||||
Vec3::new(0.5, 0.5, 0.5),
|
||||
];
|
||||
|
||||
for i in 0..8 {
|
||||
let transformed_vertex = Vec4::from((cube_vertices[i], 1.0));
|
||||
let transformed_vertex = transform * transformed_vertex;
|
||||
cube_vertices[i] = transformed_vertex.xyz();
|
||||
}
|
||||
|
||||
const CUBE_INDICES: [[u16; 4]; 6] = [
|
||||
[0, 4, 6, 2],
|
||||
[1, 3, 7, 5],
|
||||
[0, 1, 5, 4],
|
||||
[2, 6, 7, 3],
|
||||
[0, 2, 3, 1],
|
||||
[4, 5, 7, 6],
|
||||
];
|
||||
|
||||
for face in 0..6 {
|
||||
if face_mask & (1 << face) != 0 {
|
||||
self.add_cube_face_with_cube_vertices(
|
||||
&cube_vertices,
|
||||
colour,
|
||||
CUBE_INDICES[face][0],
|
||||
CUBE_INDICES[face][1],
|
||||
CUBE_INDICES[face][2],
|
||||
CUBE_INDICES[face][3],
|
||||
inward_normals,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Geometry for TriangleGeometry {
|
||||
fn upload_to_buffers(&mut self) {
|
||||
self.index_buffer = Some(unsafe {
|
||||
self.device.new_buffer_with_data(
|
||||
transmute(self.indices.as_ptr()),
|
||||
(self.indices.len() * size_of::<u16>()) as NSUInteger,
|
||||
get_managed_buffer_storage_mode(),
|
||||
)
|
||||
});
|
||||
self.vertex_position_buffer = Some(unsafe {
|
||||
self.device.new_buffer_with_data(
|
||||
transmute(self.vertices.as_ptr()),
|
||||
(self.vertices.len() * size_of::<Vec4>()) as NSUInteger,
|
||||
get_managed_buffer_storage_mode(),
|
||||
)
|
||||
});
|
||||
self.vertex_normal_buffer = Some(unsafe {
|
||||
self.device.new_buffer_with_data(
|
||||
transmute(self.normals.as_ptr()),
|
||||
(self.normals.len() * size_of::<Vec4>()) as NSUInteger,
|
||||
get_managed_buffer_storage_mode(),
|
||||
)
|
||||
});
|
||||
self.vertex_colour_buffer = Some(unsafe {
|
||||
self.device.new_buffer_with_data(
|
||||
transmute(self.colours.as_ptr()),
|
||||
(self.colours.len() * size_of::<Vec4>()) as NSUInteger,
|
||||
get_managed_buffer_storage_mode(),
|
||||
)
|
||||
});
|
||||
self.per_primitive_data_buffer = Some(unsafe {
|
||||
self.device.new_buffer_with_data(
|
||||
transmute(self.triangles.as_ptr()),
|
||||
(self.triangles.len() * size_of::<Triangle>()) as NSUInteger,
|
||||
get_managed_buffer_storage_mode(),
|
||||
)
|
||||
});
|
||||
self.index_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.did_modify_range(NSRange::new(
|
||||
0,
|
||||
self.index_buffer.as_ref().unwrap().length(),
|
||||
));
|
||||
self.vertex_position_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.did_modify_range(NSRange::new(
|
||||
0,
|
||||
self.vertex_position_buffer.as_ref().unwrap().length(),
|
||||
));
|
||||
self.vertex_normal_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.did_modify_range(NSRange::new(
|
||||
0,
|
||||
self.vertex_normal_buffer.as_ref().unwrap().length(),
|
||||
));
|
||||
self.vertex_colour_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.did_modify_range(NSRange::new(
|
||||
0,
|
||||
self.vertex_colour_buffer.as_ref().unwrap().length(),
|
||||
));
|
||||
self.per_primitive_data_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.did_modify_range(NSRange::new(
|
||||
0,
|
||||
self.per_primitive_data_buffer.as_ref().unwrap().length(),
|
||||
));
|
||||
|
||||
self.index_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.set_label(&format!("index buffer of {}", self.name));
|
||||
self.vertex_position_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.set_label(&format!("vertex position buffer of {}", self.name));
|
||||
self.vertex_normal_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.set_label(&format!("vertex normal buffer of {}", self.name));
|
||||
self.vertex_colour_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.set_label(&format!("vertex colour buffer of {}", self.name));
|
||||
self.per_primitive_data_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.set_label(&format!("per primitive data buffer of {}", self.name));
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.indices.clear();
|
||||
self.vertices.clear();
|
||||
self.normals.clear();
|
||||
self.colours.clear();
|
||||
self.triangles.clear();
|
||||
}
|
||||
|
||||
fn get_geometry_descriptor(&self) -> AccelerationStructureGeometryDescriptor {
|
||||
let descriptor = AccelerationStructureTriangleGeometryDescriptor::descriptor();
|
||||
|
||||
descriptor.set_index_buffer(Some(self.index_buffer.as_ref().unwrap()));
|
||||
descriptor.set_index_type(MTLIndexType::UInt16);
|
||||
descriptor.set_vertex_buffer(Some(self.vertex_position_buffer.as_ref().unwrap()));
|
||||
descriptor.set_vertex_stride(size_of::<Vec4>() as NSUInteger);
|
||||
descriptor.set_triangle_count((self.indices.len() / 3) as NSUInteger);
|
||||
descriptor
|
||||
.set_primitive_data_buffer(Some(self.per_primitive_data_buffer.as_ref().unwrap()));
|
||||
descriptor.set_primitive_data_stride(size_of::<Triangle>() as NSUInteger);
|
||||
descriptor.set_primitive_data_element_size(size_of::<Triangle>() as NSUInteger);
|
||||
From::from(descriptor)
|
||||
}
|
||||
|
||||
fn get_resources(&self) -> Vec<Resource> {
|
||||
vec![
|
||||
From::from(self.index_buffer.as_ref().unwrap().clone()),
|
||||
From::from(self.vertex_normal_buffer.as_ref().unwrap().clone()),
|
||||
From::from(self.vertex_colour_buffer.as_ref().unwrap().clone()),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct BoundingBox {
|
||||
pub min: Vec3,
|
||||
pub max: Vec3,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Sphere {
|
||||
pub origin_radius_squared: Vec4,
|
||||
pub colour_radius: Vec4,
|
||||
}
|
||||
|
||||
pub struct SphereGeometry {
|
||||
pub device: Device,
|
||||
pub sphere_buffer: Option<Buffer>,
|
||||
pub bounding_box_buffer: Option<Buffer>,
|
||||
pub per_primitive_data_buffer: Option<Buffer>,
|
||||
pub spheres: Vec<Sphere>,
|
||||
}
|
||||
|
||||
impl SphereGeometry {
|
||||
pub fn new(device: Device) -> Self {
|
||||
Self {
|
||||
device,
|
||||
sphere_buffer: None,
|
||||
bounding_box_buffer: None,
|
||||
per_primitive_data_buffer: None,
|
||||
spheres: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_sphere_with_origin(&mut self, origin: Vec3, radius: f32, colour: Vec3) {
|
||||
self.spheres.push(Sphere {
|
||||
origin_radius_squared: Vec4::from((origin, radius * radius)),
|
||||
colour_radius: Vec4::from((colour, radius)),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl Geometry for SphereGeometry {
|
||||
fn upload_to_buffers(&mut self) {
|
||||
self.sphere_buffer = Some(unsafe {
|
||||
self.device.new_buffer_with_data(
|
||||
transmute(self.spheres.as_ptr()),
|
||||
(self.spheres.len() * size_of::<Sphere>()) as NSUInteger,
|
||||
get_managed_buffer_storage_mode(),
|
||||
)
|
||||
});
|
||||
self.sphere_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.set_label("sphere buffer");
|
||||
let mut bounding_boxes = Vec::new();
|
||||
for sphere in &self.spheres {
|
||||
bounding_boxes.push(BoundingBox {
|
||||
min: sphere.origin_radius_squared.xyz() - sphere.colour_radius.w,
|
||||
max: sphere.origin_radius_squared.xyz() + sphere.colour_radius.w,
|
||||
});
|
||||
}
|
||||
self.bounding_box_buffer = Some(unsafe {
|
||||
self.device.new_buffer_with_data(
|
||||
transmute(bounding_boxes.as_ptr()),
|
||||
(bounding_boxes.len() * size_of::<BoundingBox>()) as NSUInteger,
|
||||
get_managed_buffer_storage_mode(),
|
||||
)
|
||||
});
|
||||
self.bounding_box_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.set_label("bounding box buffer");
|
||||
self.sphere_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.did_modify_range(NSRange::new(
|
||||
0,
|
||||
self.sphere_buffer.as_ref().unwrap().length(),
|
||||
));
|
||||
self.bounding_box_buffer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.did_modify_range(NSRange::new(
|
||||
0,
|
||||
self.bounding_box_buffer.as_ref().unwrap().length(),
|
||||
));
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.spheres.clear();
|
||||
}
|
||||
|
||||
fn get_geometry_descriptor(&self) -> AccelerationStructureGeometryDescriptor {
|
||||
let descriptor = AccelerationStructureBoundingBoxGeometryDescriptor::descriptor();
|
||||
descriptor.set_bounding_box_buffer(Some(self.bounding_box_buffer.as_ref().unwrap()));
|
||||
descriptor.set_bounding_box_count(self.spheres.len() as NSUInteger);
|
||||
descriptor.set_primitive_data_buffer(Some(&self.sphere_buffer.as_ref().unwrap()));
|
||||
descriptor.set_primitive_data_stride(size_of::<Sphere>() as NSUInteger);
|
||||
descriptor.set_primitive_data_element_size(size_of::<Sphere>() as NSUInteger);
|
||||
From::from(descriptor)
|
||||
}
|
||||
|
||||
fn get_resources(&self) -> Vec<Resource> {
|
||||
return vec![From::from(self.sphere_buffer.as_ref().unwrap().clone())];
|
||||
}
|
||||
|
||||
fn get_intersection_function_name(&self) -> Option<&str> {
|
||||
Some("sphereIntersectionFunction")
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GeometryInstance {
|
||||
pub geometry: Arc<dyn Geometry>,
|
||||
pub transform: Mat4,
|
||||
pub mask: u32,
|
||||
pub index_in_scene: NSUInteger,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct AreaLight {
|
||||
pub position: Vec4,
|
||||
pub forward: Vec4,
|
||||
pub right: Vec4,
|
||||
pub up: Vec4,
|
||||
pub colour: Vec4,
|
||||
}
|
||||
87
third-party/vendor/metal/examples/raytracing/main.rs
vendored
Normal file
87
third-party/vendor/metal/examples/raytracing/main.rs
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
extern crate objc;
|
||||
|
||||
use cocoa::{appkit::NSView, base::id as cocoa_id};
|
||||
use core_graphics_types::geometry::CGSize;
|
||||
use metal::*;
|
||||
use objc::{rc::autoreleasepool, runtime::YES};
|
||||
use std::mem;
|
||||
use winit::{
|
||||
event::{Event, WindowEvent},
|
||||
event_loop::ControlFlow,
|
||||
platform::macos::WindowExtMacOS,
|
||||
};
|
||||
|
||||
pub mod camera;
|
||||
pub mod geometry;
|
||||
pub mod renderer;
|
||||
pub mod scene;
|
||||
|
||||
fn find_raytracing_supporting_device() -> Device {
|
||||
for device in Device::all() {
|
||||
if !device.supports_raytracing() {
|
||||
continue;
|
||||
}
|
||||
if device.is_low_power() {
|
||||
continue;
|
||||
}
|
||||
return device;
|
||||
}
|
||||
|
||||
panic!("No device in this machine supports raytracing!")
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let events_loop = winit::event_loop::EventLoop::new();
|
||||
let size = winit::dpi::LogicalSize::new(800, 600);
|
||||
|
||||
let window = winit::window::WindowBuilder::new()
|
||||
.with_inner_size(size)
|
||||
.with_title("Metal Raytracing Example".to_string())
|
||||
.build(&events_loop)
|
||||
.unwrap();
|
||||
|
||||
let device = find_raytracing_supporting_device();
|
||||
|
||||
let layer = MetalLayer::new();
|
||||
layer.set_device(&device);
|
||||
layer.set_pixel_format(MTLPixelFormat::RGBA16Float);
|
||||
layer.set_presents_with_transaction(false);
|
||||
|
||||
unsafe {
|
||||
let view = window.ns_view() as cocoa_id;
|
||||
view.setWantsLayer(YES);
|
||||
view.setLayer(mem::transmute(layer.as_ref()));
|
||||
}
|
||||
|
||||
let draw_size = window.inner_size();
|
||||
let cg_size = CGSize::new(draw_size.width as f64, draw_size.height as f64);
|
||||
layer.set_drawable_size(cg_size);
|
||||
|
||||
let mut renderer = renderer::Renderer::new(device);
|
||||
renderer.window_resized(cg_size);
|
||||
|
||||
events_loop.run(move |event, _, control_flow| {
|
||||
autoreleasepool(|| {
|
||||
*control_flow = ControlFlow::Poll;
|
||||
|
||||
match event {
|
||||
Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
||||
WindowEvent::Resized(size) => {
|
||||
let size = CGSize::new(size.width as f64, size.height as f64);
|
||||
layer.set_drawable_size(size);
|
||||
renderer.window_resized(size);
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
Event::MainEventsCleared => {
|
||||
window.request_redraw();
|
||||
}
|
||||
Event::RedrawRequested(_) => {
|
||||
renderer.draw(&layer);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
512
third-party/vendor/metal/examples/raytracing/renderer.rs
vendored
Normal file
512
third-party/vendor/metal/examples/raytracing/renderer.rs
vendored
Normal file
|
|
@ -0,0 +1,512 @@
|
|||
use core_graphics_types::{base::CGFloat, geometry::CGSize};
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
ffi::c_void,
|
||||
mem::{size_of, transmute},
|
||||
ops::Index,
|
||||
sync::{Arc, Condvar, Mutex},
|
||||
};
|
||||
|
||||
use glam::{Vec3, Vec4, Vec4Swizzles};
|
||||
use rand::{thread_rng, RngCore};
|
||||
|
||||
use metal::{foreign_types::ForeignType, *};
|
||||
|
||||
use crate::{camera::Camera, geometry::get_managed_buffer_storage_mode, scene::Scene};
|
||||
|
||||
#[repr(C)]
|
||||
struct Uniforms {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub frame_index: u32,
|
||||
pub light_count: u32,
|
||||
pub camera: Camera,
|
||||
}
|
||||
|
||||
pub const MAX_FRAMES_IN_FLIGHT: NSUInteger = 3;
|
||||
pub const ALIGNED_UNIFORMS_SIZE: NSUInteger = (size_of::<Uniforms>() as NSUInteger + 255) & !255;
|
||||
pub const UNIFORM_BUFFER_SIZE: NSUInteger = MAX_FRAMES_IN_FLIGHT * ALIGNED_UNIFORMS_SIZE;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Semaphore {
|
||||
data: Arc<(Mutex<usize>, Condvar)>,
|
||||
}
|
||||
|
||||
impl Semaphore {
|
||||
fn new(capacity: usize) -> Self {
|
||||
Self {
|
||||
data: Arc::new((Mutex::new(capacity), Condvar::new())),
|
||||
}
|
||||
}
|
||||
|
||||
fn acquire(&self) {
|
||||
let mut value = self.data.0.lock().unwrap();
|
||||
while *value == 0 {
|
||||
value = self.data.1.wait(value).unwrap();
|
||||
}
|
||||
*value -= 1;
|
||||
}
|
||||
|
||||
fn release(&self) {
|
||||
let mut value = self.data.0.lock().unwrap();
|
||||
*value += 1;
|
||||
self.data.1.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Renderer {
|
||||
pub device: Device,
|
||||
pub scene: Scene,
|
||||
pub uniform_buffer: Buffer,
|
||||
pub resource_buffer: Buffer,
|
||||
pub instance_acceleration_structure: AccelerationStructure,
|
||||
pub accumulation_targets: [Texture; 2],
|
||||
pub random_texture: Texture,
|
||||
pub frame_index: NSUInteger,
|
||||
pub uniform_buffer_index: NSUInteger,
|
||||
pub uniform_buffer_offset: NSUInteger,
|
||||
pub size: CGSize,
|
||||
semaphore: Semaphore,
|
||||
pub queue: CommandQueue,
|
||||
instance_buffer: Buffer,
|
||||
intersection_function_table: IntersectionFunctionTable,
|
||||
primitive_acceleration_structures: Vec<AccelerationStructure>,
|
||||
raytracing_pipeline: ComputePipelineState,
|
||||
copy_pipeline: RenderPipelineState,
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
pub fn new(device: Device) -> Self {
|
||||
let scene = Scene::new(device.clone());
|
||||
|
||||
let library_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("examples/raytracing/shaders.metallib");
|
||||
let library = device.new_library_with_file(library_path).unwrap();
|
||||
let queue = device.new_command_queue();
|
||||
|
||||
let buffer_data = [0u8; UNIFORM_BUFFER_SIZE as usize];
|
||||
let uniform_buffer = device.new_buffer_with_data(
|
||||
buffer_data.as_ptr() as *const c_void,
|
||||
UNIFORM_BUFFER_SIZE,
|
||||
get_managed_buffer_storage_mode(),
|
||||
);
|
||||
uniform_buffer.set_label("uniform buffer");
|
||||
let resources_stride = {
|
||||
let mut max = 0;
|
||||
for geometry in &scene.geometries {
|
||||
let s = geometry.get_resources().len();
|
||||
if s > max {
|
||||
max = s;
|
||||
}
|
||||
}
|
||||
max
|
||||
};
|
||||
let mut resource_buffer_data = vec![0u64; resources_stride * scene.geometries.len()];
|
||||
for geometry_index in 0..scene.geometries.len() {
|
||||
let geometry = scene.geometries[geometry_index].as_ref();
|
||||
let resource_buffer_begin_index = resources_stride * geometry_index;
|
||||
let resources = geometry.get_resources();
|
||||
|
||||
for argument_index in 0..resources.len() {
|
||||
let resource_buffer_index = resource_buffer_begin_index + argument_index;
|
||||
let resource = resources[argument_index].clone();
|
||||
resource_buffer_data[resource_buffer_index] =
|
||||
if resource.conforms_to_protocol::<MTLBuffer>().unwrap() {
|
||||
let buffer = unsafe { Buffer::from_ptr(transmute(resource.into_ptr())) };
|
||||
buffer.gpu_address()
|
||||
} else if resource.conforms_to_protocol::<MTLTexture>().unwrap() {
|
||||
let texture = unsafe { Texture::from_ptr(transmute(resource.into_ptr())) };
|
||||
texture.gpu_resource_id()._impl
|
||||
} else {
|
||||
panic!("Unexpected resource!")
|
||||
}
|
||||
}
|
||||
}
|
||||
let resource_buffer = device.new_buffer_with_data(
|
||||
resource_buffer_data.as_ptr() as *const c_void,
|
||||
(resource_buffer_data.len() * size_of::<u64>()) as NSUInteger,
|
||||
get_managed_buffer_storage_mode(),
|
||||
);
|
||||
resource_buffer.set_label("resource buffer");
|
||||
resource_buffer.did_modify_range(NSRange::new(0, resource_buffer.length()));
|
||||
|
||||
let mut primitive_acceleration_structures = Vec::new();
|
||||
for i in 0..scene.geometries.len() {
|
||||
let mesh = scene.geometries[i].as_ref();
|
||||
let geometry_descriptor = mesh.get_geometry_descriptor();
|
||||
geometry_descriptor.set_intersection_function_table_offset(i as NSUInteger);
|
||||
let geometry_descriptors = Array::from_owned_slice(&[geometry_descriptor]);
|
||||
let accel_descriptor = PrimitiveAccelerationStructureDescriptor::descriptor();
|
||||
accel_descriptor.set_geometry_descriptors(&geometry_descriptors);
|
||||
let accel_descriptor: AccelerationStructureDescriptor = From::from(accel_descriptor);
|
||||
primitive_acceleration_structures.push(
|
||||
Self::new_acceleration_structure_with_descriptor(
|
||||
&device,
|
||||
&queue,
|
||||
&accel_descriptor,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
let mut instance_descriptors = vec![
|
||||
MTLAccelerationStructureInstanceDescriptor::default();
|
||||
scene.geometry_instances.len()
|
||||
];
|
||||
for instance_index in 0..scene.geometry_instances.len() {
|
||||
let instance = scene.geometry_instances[instance_index].as_ref();
|
||||
let geometry_index = instance.index_in_scene;
|
||||
instance_descriptors[instance_index].acceleration_structure_index =
|
||||
geometry_index as u32;
|
||||
instance_descriptors[instance_index].options =
|
||||
if instance.geometry.get_intersection_function_name().is_none() {
|
||||
MTLAccelerationStructureInstanceOptions::Opaque
|
||||
} else {
|
||||
MTLAccelerationStructureInstanceOptions::None
|
||||
};
|
||||
instance_descriptors[instance_index].intersection_function_table_offset = 0;
|
||||
instance_descriptors[instance_index].mask = instance.mask as u32;
|
||||
for column in 0..4 {
|
||||
for row in 0..3 {
|
||||
instance_descriptors[instance_index].transformation_matrix[column][row] =
|
||||
*instance.transform.col(column).index(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
let instance_buffer = device.new_buffer_with_data(
|
||||
instance_descriptors.as_ptr() as *const c_void,
|
||||
(size_of::<MTLAccelerationStructureInstanceDescriptor>()
|
||||
* scene.geometry_instances.len()) as NSUInteger,
|
||||
get_managed_buffer_storage_mode(),
|
||||
);
|
||||
instance_buffer.set_label("instance buffer");
|
||||
instance_buffer.did_modify_range(NSRange::new(0, instance_buffer.length()));
|
||||
|
||||
let accel_descriptor = InstanceAccelerationStructureDescriptor::descriptor();
|
||||
accel_descriptor.set_instanced_acceleration_structures(&Array::from_owned_slice(
|
||||
&primitive_acceleration_structures,
|
||||
));
|
||||
accel_descriptor.set_instance_count(scene.geometry_instances.len() as NSUInteger);
|
||||
accel_descriptor.set_instance_descriptor_buffer(&instance_buffer);
|
||||
let accel_descriptor: AccelerationStructureDescriptor = From::from(accel_descriptor);
|
||||
let instance_acceleration_structure =
|
||||
Self::new_acceleration_structure_with_descriptor(&device, &queue, &accel_descriptor);
|
||||
|
||||
let mut intersection_functions = BTreeMap::<String, Function>::new();
|
||||
for geometry in &scene.geometries {
|
||||
if let Some(name) = geometry.get_intersection_function_name() {
|
||||
if !intersection_functions.contains_key(name) {
|
||||
let intersection_function = Self::new_specialised_function_with_name(
|
||||
&library,
|
||||
resources_stride as u32,
|
||||
name,
|
||||
);
|
||||
intersection_functions.insert(name.to_string(), intersection_function);
|
||||
}
|
||||
}
|
||||
}
|
||||
let raytracing_function = Self::new_specialised_function_with_name(
|
||||
&library,
|
||||
resources_stride as u32,
|
||||
"raytracingKernel",
|
||||
);
|
||||
let intersection_function_array: Vec<&FunctionRef> = intersection_functions
|
||||
.values()
|
||||
.map(|f| -> &FunctionRef { f })
|
||||
.collect();
|
||||
let raytracing_pipeline = Self::new_compute_pipeline_state_with_function(
|
||||
&device,
|
||||
&raytracing_function,
|
||||
&intersection_function_array,
|
||||
);
|
||||
let intersection_function_table_descriptor = IntersectionFunctionTableDescriptor::new();
|
||||
intersection_function_table_descriptor
|
||||
.set_function_count(scene.geometries.len() as NSUInteger);
|
||||
let intersection_function_table = raytracing_pipeline
|
||||
.new_intersection_function_table_with_descriptor(
|
||||
&intersection_function_table_descriptor,
|
||||
);
|
||||
for geometry_index in 0..scene.geometries.len() {
|
||||
let geometry = scene.geometries[geometry_index].as_ref();
|
||||
if let Some(intersection_function_name) = geometry.get_intersection_function_name() {
|
||||
let intersection_function = &intersection_functions[intersection_function_name];
|
||||
let handle = raytracing_pipeline
|
||||
.function_handle_with_function(intersection_function)
|
||||
.unwrap();
|
||||
intersection_function_table.set_function(handle, geometry_index as NSUInteger);
|
||||
}
|
||||
}
|
||||
let render_descriptor = RenderPipelineDescriptor::new();
|
||||
render_descriptor
|
||||
.set_vertex_function(Some(&library.get_function("copyVertex", None).unwrap()));
|
||||
render_descriptor
|
||||
.set_fragment_function(Some(&library.get_function("copyFragment", None).unwrap()));
|
||||
render_descriptor
|
||||
.color_attachments()
|
||||
.object_at(0)
|
||||
.unwrap()
|
||||
.set_pixel_format(MTLPixelFormat::RGBA16Float);
|
||||
let copy_pipeline = device
|
||||
.new_render_pipeline_state(&render_descriptor)
|
||||
.unwrap();
|
||||
|
||||
let texture_descriptor = Self::create_target_descriptor(1024, 1024);
|
||||
let accumulation_targets = [
|
||||
device.new_texture(&texture_descriptor),
|
||||
device.new_texture(&texture_descriptor),
|
||||
];
|
||||
let random_texture = device.new_texture(&texture_descriptor);
|
||||
|
||||
Self {
|
||||
device,
|
||||
scene,
|
||||
uniform_buffer,
|
||||
resource_buffer,
|
||||
instance_acceleration_structure,
|
||||
accumulation_targets,
|
||||
random_texture,
|
||||
frame_index: 0,
|
||||
uniform_buffer_index: 0,
|
||||
uniform_buffer_offset: 0,
|
||||
size: CGSize::new(1024 as CGFloat, 1024 as CGFloat),
|
||||
semaphore: Semaphore::new((MAX_FRAMES_IN_FLIGHT - 2) as usize),
|
||||
instance_buffer,
|
||||
queue,
|
||||
intersection_function_table,
|
||||
primitive_acceleration_structures,
|
||||
raytracing_pipeline,
|
||||
copy_pipeline,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_target_descriptor(width: NSUInteger, height: NSUInteger) -> TextureDescriptor {
|
||||
let texture_descriptor = TextureDescriptor::new();
|
||||
texture_descriptor.set_pixel_format(MTLPixelFormat::RGBA32Float);
|
||||
texture_descriptor.set_texture_type(MTLTextureType::D2);
|
||||
texture_descriptor.set_width(width);
|
||||
texture_descriptor.set_height(height);
|
||||
texture_descriptor.set_storage_mode(MTLStorageMode::Private);
|
||||
texture_descriptor.set_usage(MTLTextureUsage::ShaderRead | MTLTextureUsage::ShaderWrite);
|
||||
texture_descriptor
|
||||
}
|
||||
|
||||
pub fn window_resized(&mut self, size: CGSize) {
|
||||
self.size = size;
|
||||
let texture_descriptor =
|
||||
Self::create_target_descriptor(size.width as NSUInteger, size.height as NSUInteger);
|
||||
self.accumulation_targets[0] = self.device.new_texture(&texture_descriptor);
|
||||
self.accumulation_targets[1] = self.device.new_texture(&texture_descriptor);
|
||||
texture_descriptor.set_pixel_format(MTLPixelFormat::R32Uint);
|
||||
texture_descriptor.set_usage(MTLTextureUsage::ShaderRead);
|
||||
texture_descriptor.set_storage_mode(MTLStorageMode::Managed);
|
||||
self.random_texture = self.device.new_texture(&texture_descriptor);
|
||||
let mut rng = thread_rng();
|
||||
let mut random_values = vec![0u32; (size.width * size.height) as usize];
|
||||
for v in &mut random_values {
|
||||
*v = rng.next_u32();
|
||||
}
|
||||
self.random_texture.replace_region(
|
||||
MTLRegion::new_2d(0, 0, size.width as NSUInteger, size.height as NSUInteger),
|
||||
0,
|
||||
random_values.as_ptr() as *const c_void,
|
||||
size_of::<u32>() as NSUInteger * size.width as NSUInteger,
|
||||
);
|
||||
self.frame_index = 0;
|
||||
}
|
||||
|
||||
fn update_uniforms(&mut self) {
|
||||
self.uniform_buffer_offset = ALIGNED_UNIFORMS_SIZE * self.uniform_buffer_index;
|
||||
|
||||
let uniforms = unsafe {
|
||||
&mut *((self.uniform_buffer.contents() as *mut u8)
|
||||
.add(self.uniform_buffer_offset as usize) as *mut Uniforms)
|
||||
};
|
||||
|
||||
let position = self.scene.camera.position;
|
||||
let target = self.scene.camera.forward;
|
||||
let up = self.scene.camera.up;
|
||||
|
||||
let forward = Vec3::normalize(target.xyz() - position.xyz());
|
||||
let right = Vec3::normalize(Vec3::cross(forward, up.xyz()));
|
||||
let up = Vec3::normalize(Vec3::cross(right, forward));
|
||||
|
||||
uniforms.camera.position = position;
|
||||
uniforms.camera.forward = Vec4::from((forward, 0.0));
|
||||
uniforms.camera.right = Vec4::from((right, 0.0));
|
||||
uniforms.camera.up = Vec4::from((up, 0.0));
|
||||
|
||||
let field_of_view = 45.0 * (std::f32::consts::PI / 180.0);
|
||||
let aspect_ratio = self.size.width as f32 / self.size.height as f32;
|
||||
let image_plane_height = f32::tan(field_of_view / 2.0);
|
||||
let image_plane_width = aspect_ratio * image_plane_height;
|
||||
|
||||
uniforms.camera.right *= image_plane_width;
|
||||
uniforms.camera.up *= image_plane_height;
|
||||
|
||||
uniforms.width = self.size.width as u32;
|
||||
uniforms.height = self.size.height as u32;
|
||||
|
||||
uniforms.frame_index = self.frame_index as u32;
|
||||
self.frame_index += 1;
|
||||
|
||||
uniforms.light_count = self.scene.lights.len() as u32;
|
||||
|
||||
self.uniform_buffer.did_modify_range(NSRange {
|
||||
location: self.uniform_buffer_offset,
|
||||
length: ALIGNED_UNIFORMS_SIZE,
|
||||
});
|
||||
|
||||
self.uniform_buffer_index = (self.uniform_buffer_index + 1) % MAX_FRAMES_IN_FLIGHT;
|
||||
}
|
||||
|
||||
pub fn draw(&mut self, layer: &MetalLayer) {
|
||||
self.semaphore.acquire();
|
||||
self.update_uniforms();
|
||||
let command_buffer = self.queue.new_command_buffer();
|
||||
let sem = self.semaphore.clone();
|
||||
let block = block::ConcreteBlock::new(move |_| {
|
||||
sem.release();
|
||||
})
|
||||
.copy();
|
||||
command_buffer.add_completed_handler(&block);
|
||||
let width = self.size.width as NSUInteger;
|
||||
let height = self.size.height as NSUInteger;
|
||||
let threads_per_thread_group = MTLSize::new(8, 8, 1);
|
||||
let thread_groups = MTLSize::new(
|
||||
(width + threads_per_thread_group.width - 1) / threads_per_thread_group.width,
|
||||
(height + threads_per_thread_group.height - 1) / threads_per_thread_group.height,
|
||||
1,
|
||||
);
|
||||
let compute_encoder = command_buffer.new_compute_command_encoder();
|
||||
compute_encoder.set_buffer(0, Some(&self.uniform_buffer), self.uniform_buffer_offset);
|
||||
compute_encoder.set_buffer(2, Some(&self.instance_buffer), 0);
|
||||
compute_encoder.set_buffer(3, Some(&self.scene.lights_buffer), 0);
|
||||
compute_encoder.set_acceleration_structure(4, Some(&self.instance_acceleration_structure));
|
||||
compute_encoder.set_intersection_function_table(5, Some(&self.intersection_function_table));
|
||||
compute_encoder.set_texture(0, Some(&self.random_texture));
|
||||
compute_encoder.set_texture(1, Some(&self.accumulation_targets[0]));
|
||||
compute_encoder.set_texture(2, Some(&self.accumulation_targets[1]));
|
||||
for geometry in &self.scene.geometries {
|
||||
for resource in geometry.get_resources() {
|
||||
compute_encoder.use_resource(&resource, MTLResourceUsage::Read);
|
||||
}
|
||||
}
|
||||
for primitive_acceleration_structure in &self.primitive_acceleration_structures {
|
||||
let resource: Resource = From::from(primitive_acceleration_structure.clone());
|
||||
compute_encoder.use_resource(&resource, MTLResourceUsage::Read);
|
||||
}
|
||||
compute_encoder.set_compute_pipeline_state(&self.raytracing_pipeline);
|
||||
compute_encoder.dispatch_thread_groups(thread_groups, threads_per_thread_group);
|
||||
compute_encoder.end_encoding();
|
||||
(self.accumulation_targets[0], self.accumulation_targets[1]) = (
|
||||
self.accumulation_targets[1].clone(),
|
||||
self.accumulation_targets[0].clone(),
|
||||
);
|
||||
if let Some(drawable) = layer.next_drawable() {
|
||||
let render_pass_descriptor = RenderPassDescriptor::new();
|
||||
let colour_attachment = render_pass_descriptor
|
||||
.color_attachments()
|
||||
.object_at(0)
|
||||
.unwrap();
|
||||
colour_attachment.set_texture(Some(drawable.texture()));
|
||||
colour_attachment.set_load_action(MTLLoadAction::Clear);
|
||||
colour_attachment.set_clear_color(MTLClearColor::new(0.0, 0.0, 0.0, 1.0));
|
||||
let render_encoder = command_buffer.new_render_command_encoder(render_pass_descriptor);
|
||||
render_encoder.set_render_pipeline_state(&self.copy_pipeline);
|
||||
render_encoder.set_fragment_texture(0, Some(&self.accumulation_targets[0]));
|
||||
render_encoder.draw_primitives(MTLPrimitiveType::Triangle, 0, 6);
|
||||
render_encoder.end_encoding();
|
||||
command_buffer.present_drawable(&drawable);
|
||||
}
|
||||
command_buffer.commit();
|
||||
}
|
||||
|
||||
fn new_acceleration_structure_with_descriptor(
|
||||
device: &Device,
|
||||
queue: &CommandQueue,
|
||||
descriptor: &AccelerationStructureDescriptorRef,
|
||||
) -> AccelerationStructure {
|
||||
let accel_sizes = device.acceleration_structure_sizes_with_descriptor(descriptor);
|
||||
let acceleration_structure =
|
||||
device.new_acceleration_structure_with_size(accel_sizes.acceleration_structure_size);
|
||||
let scratch_buffer = device.new_buffer(
|
||||
accel_sizes.build_scratch_buffer_size,
|
||||
MTLResourceOptions::StorageModePrivate,
|
||||
);
|
||||
let command_buffer = queue.new_command_buffer();
|
||||
let command_encoder = command_buffer.new_acceleration_structure_command_encoder();
|
||||
let compacted_size_buffer = device.new_buffer(
|
||||
size_of::<u32>() as NSUInteger,
|
||||
MTLResourceOptions::StorageModeShared,
|
||||
);
|
||||
command_encoder.build_acceleration_structure(
|
||||
&acceleration_structure,
|
||||
&descriptor,
|
||||
&scratch_buffer,
|
||||
0,
|
||||
);
|
||||
command_encoder.write_compacted_acceleration_structure_size(
|
||||
&acceleration_structure,
|
||||
&compacted_size_buffer,
|
||||
0,
|
||||
);
|
||||
command_encoder.end_encoding();
|
||||
command_buffer.commit();
|
||||
command_buffer.wait_until_completed();
|
||||
let compacted_size: *const u32 = unsafe { transmute(compacted_size_buffer.contents()) };
|
||||
let compacted_size = unsafe { *compacted_size } as NSUInteger;
|
||||
let compacted_acceleration_structure =
|
||||
device.new_acceleration_structure_with_size(compacted_size);
|
||||
let command_buffer = queue.new_command_buffer();
|
||||
let command_encoder = command_buffer.new_acceleration_structure_command_encoder();
|
||||
command_encoder.copy_and_compact_acceleration_structure(
|
||||
&acceleration_structure,
|
||||
&compacted_acceleration_structure,
|
||||
);
|
||||
command_encoder.end_encoding();
|
||||
command_buffer.commit();
|
||||
compacted_acceleration_structure
|
||||
}
|
||||
|
||||
fn new_specialised_function_with_name(
|
||||
library: &Library,
|
||||
resources_stride: u32,
|
||||
name: &str,
|
||||
) -> Function {
|
||||
let constants = FunctionConstantValues::new();
|
||||
let resources_stride = resources_stride * size_of::<u64>() as u32;
|
||||
constants.set_constant_value_at_index(
|
||||
&resources_stride as *const u32 as *const c_void,
|
||||
MTLDataType::UInt,
|
||||
0,
|
||||
);
|
||||
let v = true;
|
||||
constants.set_constant_value_at_index(
|
||||
&v as *const bool as *const c_void,
|
||||
MTLDataType::Bool,
|
||||
1,
|
||||
);
|
||||
constants.set_constant_value_at_index(
|
||||
&v as *const bool as *const c_void,
|
||||
MTLDataType::Bool,
|
||||
2,
|
||||
);
|
||||
library.get_function(name, Some(constants)).unwrap()
|
||||
}
|
||||
|
||||
fn new_compute_pipeline_state_with_function(
|
||||
device: &Device,
|
||||
function: &Function,
|
||||
linked_functions: &[&FunctionRef],
|
||||
) -> ComputePipelineState {
|
||||
let linked_functions = {
|
||||
let lf = LinkedFunctions::new();
|
||||
lf.set_functions(linked_functions);
|
||||
lf
|
||||
};
|
||||
let descriptor = ComputePipelineDescriptor::new();
|
||||
descriptor.set_compute_function(Some(function));
|
||||
descriptor.set_linked_functions(linked_functions.as_ref());
|
||||
descriptor.set_thread_group_size_is_multiple_of_thread_execution_width(true);
|
||||
device.new_compute_pipeline_state(&descriptor).unwrap()
|
||||
}
|
||||
}
|
||||
135
third-party/vendor/metal/examples/raytracing/scene.rs
vendored
Normal file
135
third-party/vendor/metal/examples/raytracing/scene.rs
vendored
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
use std::{ffi::c_void, mem::size_of, sync::Arc};
|
||||
|
||||
use glam::{Mat4, Vec3, Vec4};
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use metal::{Buffer, Device, NSRange, NSUInteger};
|
||||
|
||||
use super::{camera::Camera, geometry::*};
|
||||
|
||||
pub struct Scene {
|
||||
pub device: Device,
|
||||
pub camera: Camera,
|
||||
pub geometries: Vec<Arc<dyn Geometry>>,
|
||||
pub geometry_instances: Vec<Arc<GeometryInstance>>,
|
||||
pub lights: Vec<AreaLight>,
|
||||
pub lights_buffer: Buffer,
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
pub fn new(device: Device) -> Self {
|
||||
let mut geometries = Vec::<Arc<dyn Geometry>>::new();
|
||||
let mut light_mesh = TriangleGeometry::new(device.clone(), "light".to_string());
|
||||
let transform = Mat4::from_translation(Vec3::new(0.0, 1.0, 0.0))
|
||||
* Mat4::from_scale(Vec3::new(0.5, 1.98, 0.5));
|
||||
light_mesh.add_cube_with_faces(
|
||||
FACE_MASK_POSITIVE_Y,
|
||||
Vec3::new(1.0, 1.0, 1.0),
|
||||
transform,
|
||||
true,
|
||||
);
|
||||
light_mesh.upload_to_buffers();
|
||||
let light_mesh = Arc::new(light_mesh);
|
||||
geometries.push(light_mesh.clone());
|
||||
|
||||
let mut geometry_mesh = TriangleGeometry::new(device.clone(), "geometry".to_string());
|
||||
let transform = Mat4::from_translation(Vec3::new(0.0, 1.0, 0.0))
|
||||
* Mat4::from_scale(Vec3::new(2.0, 2.0, 2.0));
|
||||
geometry_mesh.add_cube_with_faces(
|
||||
FACE_MASK_NEGATIVE_Y | FACE_MASK_POSITIVE_Y | FACE_MASK_NEGATIVE_Z,
|
||||
Vec3::new(0.725, 0.71, 0.68),
|
||||
transform,
|
||||
true,
|
||||
);
|
||||
geometry_mesh.add_cube_with_faces(
|
||||
FACE_MASK_NEGATIVE_X,
|
||||
Vec3::new(0.63, 0.065, 0.05),
|
||||
transform,
|
||||
true,
|
||||
);
|
||||
geometry_mesh.add_cube_with_faces(
|
||||
FACE_MASK_POSITIVE_X,
|
||||
Vec3::new(0.14, 0.45, 0.091),
|
||||
transform,
|
||||
true,
|
||||
);
|
||||
let transform = Mat4::from_translation(Vec3::new(-0.335, 0.6, -0.29))
|
||||
* Mat4::from_rotation_y(0.3)
|
||||
* Mat4::from_scale(Vec3::new(0.6, 1.2, 0.6));
|
||||
geometry_mesh.add_cube_with_faces(
|
||||
FACE_MASK_ALL,
|
||||
Vec3::new(0.725, 0.71, 0.68),
|
||||
transform,
|
||||
false,
|
||||
);
|
||||
geometry_mesh.upload_to_buffers();
|
||||
let geometry_mesh = Arc::new(geometry_mesh);
|
||||
geometries.push(geometry_mesh.clone());
|
||||
|
||||
let mut sphere_geometry = SphereGeometry::new(device.clone());
|
||||
sphere_geometry.add_sphere_with_origin(
|
||||
Vec3::new(0.3275, 0.3, 0.3725),
|
||||
0.3,
|
||||
Vec3::new(0.725, 0.71, 0.68),
|
||||
);
|
||||
sphere_geometry.upload_to_buffers();
|
||||
let sphere_geometry = Arc::new(sphere_geometry);
|
||||
geometries.push(sphere_geometry.clone());
|
||||
|
||||
let mut rng = thread_rng();
|
||||
let mut geometry_instances = Vec::new();
|
||||
let mut lights = Vec::new();
|
||||
for y in -1..2 {
|
||||
for x in -1..2 {
|
||||
let transform =
|
||||
Mat4::from_translation(Vec3::new(x as f32 * 2.5, y as f32 * 2.5, 0.0));
|
||||
geometry_instances.push(Arc::new(GeometryInstance {
|
||||
geometry: light_mesh.clone(),
|
||||
transform,
|
||||
mask: GEOMETRY_MASK_LIGHT,
|
||||
index_in_scene: 0,
|
||||
}));
|
||||
geometry_instances.push(Arc::new(GeometryInstance {
|
||||
geometry: geometry_mesh.clone(),
|
||||
transform,
|
||||
mask: GEOMETRY_MASK_TRIANGLE,
|
||||
index_in_scene: 1,
|
||||
}));
|
||||
geometry_instances.push(Arc::new(GeometryInstance {
|
||||
geometry: sphere_geometry.clone(),
|
||||
transform,
|
||||
mask: GEOMETRY_MASK_SPHERE,
|
||||
index_in_scene: 2,
|
||||
}));
|
||||
lights.push(AreaLight {
|
||||
position: Vec4::new(x as f32 * 2.5, y as f32 * 2.5 + 1.98, 0.0, 0.0),
|
||||
forward: Vec4::new(0.0, -1.0, 0.0, 0.0),
|
||||
right: Vec4::new(0.25, 0.0, 0.0, 0.0),
|
||||
up: Vec4::new(0.0, 0.0, 0.25, 0.0),
|
||||
colour: Vec4::new(
|
||||
rng.gen_range(0f32..=1.0),
|
||||
rng.gen_range(0f32..=1.0),
|
||||
rng.gen_range(0f32..=1.0),
|
||||
0.0,
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
let lights_buffer = device.new_buffer_with_data(
|
||||
lights.as_ptr() as *const c_void,
|
||||
(lights.len() * size_of::<AreaLight>()) as NSUInteger,
|
||||
get_managed_buffer_storage_mode(),
|
||||
);
|
||||
lights_buffer.did_modify_range(NSRange::new(0, lights_buffer.length()));
|
||||
lights_buffer.set_label("lights buffer");
|
||||
|
||||
Self {
|
||||
device,
|
||||
camera: Camera::new(),
|
||||
geometries,
|
||||
geometry_instances,
|
||||
lights,
|
||||
lights_buffer,
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
third-party/vendor/metal/examples/raytracing/screenshot.png
vendored
Normal file
BIN
third-party/vendor/metal/examples/raytracing/screenshot.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 MiB |
598
third-party/vendor/metal/examples/raytracing/shaders.metal
vendored
Normal file
598
third-party/vendor/metal/examples/raytracing/shaders.metal
vendored
Normal file
|
|
@ -0,0 +1,598 @@
|
|||
/*
|
||||
See LICENSE folder for this sample’s licensing information.
|
||||
|
||||
Abstract:
|
||||
The Metal shaders used for this sample.
|
||||
*/
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
using namespace raytracing;
|
||||
|
||||
|
||||
#define GEOMETRY_MASK_TRIANGLE 1
|
||||
#define GEOMETRY_MASK_SPHERE 2
|
||||
#define GEOMETRY_MASK_LIGHT 4
|
||||
|
||||
#define GEOMETRY_MASK_GEOMETRY (GEOMETRY_MASK_TRIANGLE | GEOMETRY_MASK_SPHERE)
|
||||
|
||||
#define RAY_MASK_PRIMARY (GEOMETRY_MASK_GEOMETRY | GEOMETRY_MASK_LIGHT)
|
||||
#define RAY_MASK_SHADOW GEOMETRY_MASK_GEOMETRY
|
||||
#define RAY_MASK_SECONDARY GEOMETRY_MASK_GEOMETRY
|
||||
|
||||
struct Camera {
|
||||
vector_float3 position;
|
||||
vector_float3 right;
|
||||
vector_float3 up;
|
||||
vector_float3 forward;
|
||||
};
|
||||
|
||||
struct AreaLight {
|
||||
vector_float3 position;
|
||||
vector_float3 forward;
|
||||
vector_float3 right;
|
||||
vector_float3 up;
|
||||
vector_float3 color;
|
||||
};
|
||||
|
||||
struct Uniforms {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int frameIndex;
|
||||
unsigned int lightCount;
|
||||
Camera camera;
|
||||
};
|
||||
|
||||
struct Sphere {
|
||||
packed_float3 origin;
|
||||
float radiusSquared;
|
||||
packed_float3 color;
|
||||
float radius;
|
||||
};
|
||||
|
||||
struct Triangle {
|
||||
vector_float3 normals[3];
|
||||
vector_float3 colors[3];
|
||||
};
|
||||
|
||||
constant unsigned int resourcesStride [[function_constant(0)]];
|
||||
constant bool useIntersectionFunctions [[function_constant(1)]];
|
||||
constant bool usePerPrimitiveData [[function_constant(2)]];
|
||||
constant bool useResourcesBuffer = !usePerPrimitiveData;
|
||||
|
||||
constant unsigned int primes[] = {
|
||||
2, 3, 5, 7,
|
||||
11, 13, 17, 19,
|
||||
23, 29, 31, 37,
|
||||
41, 43, 47, 53,
|
||||
59, 61, 67, 71,
|
||||
73, 79, 83, 89
|
||||
};
|
||||
|
||||
// Returns the i'th element of the Halton sequence using the d'th prime number as a
|
||||
// base. The Halton sequence is a low discrepency sequence: the values appear
|
||||
// random, but are more evenly distributed than a purely random sequence. Each random
|
||||
// value used to render the image uses a different independent dimension, `d`,
|
||||
// and each sample (frame) uses a different index `i`. To decorrelate each pixel,
|
||||
// you can apply a random offset to `i`.
|
||||
float halton(unsigned int i, unsigned int d) {
|
||||
unsigned int b = primes[d];
|
||||
|
||||
float f = 1.0f;
|
||||
float invB = 1.0f / b;
|
||||
|
||||
float r = 0;
|
||||
|
||||
while (i > 0) {
|
||||
f = f * invB;
|
||||
r = r + f * (i % b);
|
||||
i = i / b;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// Interpolates the vertex attribute of an arbitrary type across the surface of a triangle
|
||||
// given the barycentric coordinates and triangle index in an intersection structure.
|
||||
template<typename T, typename IndexType>
|
||||
inline T interpolateVertexAttribute(device T *attributes,
|
||||
IndexType i0,
|
||||
IndexType i1,
|
||||
IndexType i2,
|
||||
float2 uv) {
|
||||
// Look up value for each vertex.
|
||||
const T T0 = attributes[i0];
|
||||
const T T1 = attributes[i1];
|
||||
const T T2 = attributes[i2];
|
||||
|
||||
// Compute the sum of the vertex attributes weighted by the barycentric coordinates.
|
||||
// The barycentric coordinates sum to one.
|
||||
return (1.0f - uv.x - uv.y) * T0 + uv.x * T1 + uv.y * T2;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T interpolateVertexAttribute(thread T *attributes, float2 uv) {
|
||||
// Look up the value for each vertex.
|
||||
const T T0 = attributes[0];
|
||||
const T T1 = attributes[1];
|
||||
const T T2 = attributes[2];
|
||||
|
||||
// Compute the sum of the vertex attributes weighted by the barycentric coordinates.
|
||||
// The barycentric coordinates sum to one.
|
||||
return (1.0f - uv.x - uv.y) * T0 + uv.x * T1 + uv.y * T2;
|
||||
}
|
||||
|
||||
// Uses the inversion method to map two uniformly random numbers to a 3D
|
||||
// unit hemisphere, where the probability of a given sample is proportional to the cosine
|
||||
// of the angle between the sample direction and the "up" direction (0, 1, 0).
|
||||
inline float3 sampleCosineWeightedHemisphere(float2 u) {
|
||||
float phi = 2.0f * M_PI_F * u.x;
|
||||
|
||||
float cos_phi;
|
||||
float sin_phi = sincos(phi, cos_phi);
|
||||
|
||||
float cos_theta = sqrt(u.y);
|
||||
float sin_theta = sqrt(1.0f - cos_theta * cos_theta);
|
||||
|
||||
return float3(sin_theta * cos_phi, cos_theta, sin_theta * sin_phi);
|
||||
}
|
||||
|
||||
// Maps two uniformly random numbers to the surface of a 2D area light
|
||||
// source and returns the direction to this point, the amount of light that travels
|
||||
// between the intersection point and the sample point on the light source, as well
|
||||
// as the distance between these two points.
|
||||
|
||||
inline void sampleAreaLight(constant AreaLight & light,
|
||||
float2 u,
|
||||
float3 position,
|
||||
thread float3 & lightDirection,
|
||||
thread float3 & lightColor,
|
||||
thread float & lightDistance)
|
||||
{
|
||||
// Map to -1..1
|
||||
u = u * 2.0f - 1.0f;
|
||||
|
||||
// Transform into the light's coordinate system.
|
||||
float3 samplePosition = light.position +
|
||||
light.right * u.x +
|
||||
light.up * u.y;
|
||||
|
||||
// Compute the vector from sample point on the light source to intersection point.
|
||||
lightDirection = samplePosition - position;
|
||||
|
||||
lightDistance = length(lightDirection);
|
||||
|
||||
float inverseLightDistance = 1.0f / max(lightDistance, 1e-3f);
|
||||
|
||||
// Normalize the light direction.
|
||||
lightDirection *= inverseLightDistance;
|
||||
|
||||
// Start with the light's color.
|
||||
lightColor = light.color;
|
||||
|
||||
// Light falls off with the inverse square of the distance to the intersection point.
|
||||
lightColor *= (inverseLightDistance * inverseLightDistance);
|
||||
|
||||
// Light also falls off with the cosine of the angle between the intersection point
|
||||
// and the light source.
|
||||
lightColor *= saturate(dot(-lightDirection, light.forward));
|
||||
}
|
||||
|
||||
// Aligns a direction on the unit hemisphere such that the hemisphere's "up" direction
|
||||
// (0, 1, 0) maps to the given surface normal direction.
|
||||
inline float3 alignHemisphereWithNormal(float3 sample, float3 normal) {
|
||||
// Set the "up" vector to the normal
|
||||
float3 up = normal;
|
||||
|
||||
// Find an arbitrary direction perpendicular to the normal, which becomes the
|
||||
// "right" vector.
|
||||
float3 right = normalize(cross(normal, float3(0.0072f, 1.0f, 0.0034f)));
|
||||
|
||||
// Find a third vector perpendicular to the previous two, which becomes the
|
||||
// "forward" vector.
|
||||
float3 forward = cross(right, up);
|
||||
|
||||
// Map the direction on the unit hemisphere to the coordinate system aligned
|
||||
// with the normal.
|
||||
return sample.x * right + sample.y * up + sample.z * forward;
|
||||
}
|
||||
|
||||
// Return the type for a bounding box intersection function.
|
||||
struct BoundingBoxIntersection {
|
||||
bool accept [[accept_intersection]]; // Whether to accept or reject the intersection.
|
||||
float distance [[distance]]; // Distance from the ray origin to the intersection point.
|
||||
};
|
||||
|
||||
// Resources for a piece of triangle geometry.
|
||||
struct TriangleResources {
|
||||
device uint16_t *indices;
|
||||
device float3 *vertexNormals;
|
||||
device float3 *vertexColors;
|
||||
};
|
||||
|
||||
// Resources for a piece of sphere geometry.
|
||||
struct SphereResources {
|
||||
device Sphere *spheres;
|
||||
};
|
||||
|
||||
/*
|
||||
Custom sphere intersection function. The [[intersection]] keyword marks this as an intersection
|
||||
function. The [[bounding_box]] keyword means that this intersection function handles intersecting rays
|
||||
with bounding box primitives. To create sphere primitives, the sample creates bounding boxes that
|
||||
enclose the sphere primitives.
|
||||
|
||||
The [[triangle_data]] and [[instancing]] keywords indicate that the intersector that calls this
|
||||
intersection function returns barycentric coordinates for triangle intersections and traverses
|
||||
an instance acceleration structure. These keywords must match between the intersection functions,
|
||||
intersection function table, intersector, and intersection result to ensure that Metal propagates
|
||||
data correctly between stages. Using fewer tags when possible may result in better performance,
|
||||
as Metal may need to store less data and pass less data between stages. For example, if you do not
|
||||
need barycentric coordinates, omitting [[triangle_data]] means Metal can avoid computing and storing
|
||||
them.
|
||||
|
||||
The arguments to the intersection function contain information about the ray, primitive to be
|
||||
tested, and so on. The ray intersector provides this datas when it calls the intersection function.
|
||||
Metal provides other built-in arguments, but this sample doesn't use them.
|
||||
*/
|
||||
[[intersection(bounding_box, triangle_data, instancing)]]
|
||||
BoundingBoxIntersection sphereIntersectionFunction(// Ray parameters passed to the ray intersector below
|
||||
float3 origin [[origin]],
|
||||
float3 direction [[direction]],
|
||||
float minDistance [[min_distance]],
|
||||
float maxDistance [[max_distance]],
|
||||
// Information about the primitive.
|
||||
unsigned int primitiveIndex [[primitive_id]],
|
||||
unsigned int geometryIndex [[geometry_intersection_function_table_offset]],
|
||||
// Custom resources bound to the intersection function table.
|
||||
device void *resources [[buffer(0), function_constant(useResourcesBuffer)]]
|
||||
,const device void* perPrimitiveData [[primitive_data]])
|
||||
{
|
||||
Sphere sphere;
|
||||
// Look up the resources for this piece of sphere geometry.
|
||||
if (usePerPrimitiveData) {
|
||||
// Per-primitive data points to data from the specified buffer as was configured in the MTLAccelerationStructureBoundingBoxGeometryDescriptor.
|
||||
sphere = *(const device Sphere*)perPrimitiveData;
|
||||
} else
|
||||
{
|
||||
device SphereResources& sphereResources = *(device SphereResources *)((device char *)resources + resourcesStride * geometryIndex);
|
||||
// Get the actual sphere enclosed in this bounding box.
|
||||
sphere = sphereResources.spheres[primitiveIndex];
|
||||
}
|
||||
|
||||
// Check for intersection between the ray and sphere mathematically.
|
||||
float3 oc = origin - sphere.origin;
|
||||
|
||||
float a = dot(direction, direction);
|
||||
float b = 2 * dot(oc, direction);
|
||||
float c = dot(oc, oc) - sphere.radiusSquared;
|
||||
|
||||
float disc = b * b - 4 * a * c;
|
||||
|
||||
BoundingBoxIntersection ret;
|
||||
|
||||
if (disc <= 0.0f) {
|
||||
// If the ray missed the sphere, return false.
|
||||
ret.accept = false;
|
||||
}
|
||||
else {
|
||||
// Otherwise, compute the intersection distance.
|
||||
ret.distance = (-b - sqrt(disc)) / (2 * a);
|
||||
|
||||
// The intersection function must also check whether the intersection distance is
|
||||
// within the acceptable range. Intersection functions do not run in any particular order,
|
||||
// so the maximum distance may be different from the one passed into the ray intersector.
|
||||
ret.accept = ret.distance >= minDistance && ret.distance <= maxDistance;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
__attribute__((always_inline))
|
||||
float3 transformPoint(float3 p, float4x4 transform) {
|
||||
return (transform * float4(p.x, p.y, p.z, 1.0f)).xyz;
|
||||
}
|
||||
|
||||
__attribute__((always_inline))
|
||||
float3 transformDirection(float3 p, float4x4 transform) {
|
||||
return (transform * float4(p.x, p.y, p.z, 0.0f)).xyz;
|
||||
}
|
||||
|
||||
// Main ray tracing kernel.
|
||||
kernel void raytracingKernel(
|
||||
uint2 tid [[thread_position_in_grid]],
|
||||
constant Uniforms & uniforms [[buffer(0)]],
|
||||
texture2d<unsigned int> randomTex [[texture(0)]],
|
||||
texture2d<float> prevTex [[texture(1)]],
|
||||
texture2d<float, access::write> dstTex [[texture(2)]],
|
||||
device void *resources [[buffer(1), function_constant(useResourcesBuffer)]],
|
||||
constant MTLAccelerationStructureInstanceDescriptor *instances [[buffer(2)]],
|
||||
constant AreaLight *areaLights [[buffer(3)]],
|
||||
instance_acceleration_structure accelerationStructure [[buffer(4)]],
|
||||
intersection_function_table<triangle_data, instancing> intersectionFunctionTable [[buffer(5)]]
|
||||
)
|
||||
{
|
||||
// The sample aligns the thread count to the threadgroup size, which means the thread count
|
||||
// may be different than the bounds of the texture. Test to make sure this thread
|
||||
// is referencing a pixel within the bounds of the texture.
|
||||
if (tid.x >= uniforms.width || tid.y >= uniforms.height) return;
|
||||
|
||||
// The ray to cast.
|
||||
ray ray;
|
||||
|
||||
// Pixel coordinates for this thread.
|
||||
float2 pixel = (float2)tid;
|
||||
|
||||
// Apply a random offset to the random number index to decorrelate pixels.
|
||||
unsigned int offset = randomTex.read(tid).x;
|
||||
|
||||
// Add a random offset to the pixel coordinates for antialiasing.
|
||||
float2 r = float2(halton(offset + uniforms.frameIndex, 0),
|
||||
halton(offset + uniforms.frameIndex, 1));
|
||||
|
||||
pixel += r;
|
||||
|
||||
// Map pixel coordinates to -1..1.
|
||||
float2 uv = (float2)pixel / float2(uniforms.width, uniforms.height);
|
||||
uv = uv * 2.0f - 1.0f;
|
||||
|
||||
constant Camera & camera = uniforms.camera;
|
||||
|
||||
// Rays start at the camera position.
|
||||
ray.origin = camera.position;
|
||||
|
||||
// Map normalized pixel coordinates into camera's coordinate system.
|
||||
ray.direction = normalize(uv.x * camera.right +
|
||||
uv.y * camera.up +
|
||||
camera.forward);
|
||||
|
||||
// Don't limit intersection distance.
|
||||
ray.max_distance = INFINITY;
|
||||
|
||||
// Start with a fully white color. The kernel scales the light each time the
|
||||
// ray bounces off of a surface, based on how much of each light component
|
||||
// the surface absorbs.
|
||||
float3 color = float3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
float3 accumulatedColor = float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
// Create an intersector to test for intersection between the ray and the geometry in the scene.
|
||||
intersector<triangle_data, instancing> i;
|
||||
|
||||
// If the sample isn't using intersection functions, provide some hints to Metal for
|
||||
// better performance.
|
||||
if (!useIntersectionFunctions) {
|
||||
i.assume_geometry_type(geometry_type::triangle);
|
||||
i.force_opacity(forced_opacity::opaque);
|
||||
}
|
||||
|
||||
typename intersector<triangle_data, instancing>::result_type intersection;
|
||||
|
||||
// Simulate up to three ray bounces. Each bounce propagates light backward along the
|
||||
// ray's path toward the camera.
|
||||
for (int bounce = 0; bounce < 3; bounce++) {
|
||||
// Get the closest intersection, not the first intersection. This is the default, but
|
||||
// the sample adjusts this property below when it casts shadow rays.
|
||||
i.accept_any_intersection(false);
|
||||
|
||||
// Check for intersection between the ray and the acceleration structure. If the sample
|
||||
// isn't using intersection functions, it doesn't need to include one.
|
||||
if (useIntersectionFunctions)
|
||||
intersection = i.intersect(ray, accelerationStructure, bounce == 0 ? RAY_MASK_PRIMARY : RAY_MASK_SECONDARY, intersectionFunctionTable);
|
||||
else
|
||||
intersection = i.intersect(ray, accelerationStructure, bounce == 0 ? RAY_MASK_PRIMARY : RAY_MASK_SECONDARY);
|
||||
|
||||
// Stop if the ray didn't hit anything and has bounced out of the scene.
|
||||
if (intersection.type == intersection_type::none)
|
||||
break;
|
||||
|
||||
unsigned int instanceIndex = intersection.instance_id;
|
||||
|
||||
// Look up the mask for this instance, which indicates what type of geometry the ray hit.
|
||||
unsigned int mask = instances[instanceIndex].mask;
|
||||
|
||||
// If the ray hit a light source, set the color to white, and stop immediately.
|
||||
if (mask == GEOMETRY_MASK_LIGHT) {
|
||||
accumulatedColor = float3(1.0f, 1.0f, 1.0f);
|
||||
break;
|
||||
}
|
||||
|
||||
// The ray hit something. Look up the transformation matrix for this instance.
|
||||
float4x4 objectToWorldSpaceTransform(1.0f);
|
||||
|
||||
for (int column = 0; column < 4; column++)
|
||||
for (int row = 0; row < 3; row++)
|
||||
objectToWorldSpaceTransform[column][row] = instances[instanceIndex].transformationMatrix[column][row];
|
||||
|
||||
// Compute the intersection point in world space.
|
||||
float3 worldSpaceIntersectionPoint = ray.origin + ray.direction * intersection.distance;
|
||||
|
||||
unsigned primitiveIndex = intersection.primitive_id;
|
||||
unsigned int geometryIndex = instances[instanceIndex].accelerationStructureIndex;
|
||||
float2 barycentric_coords = intersection.triangle_barycentric_coord;
|
||||
|
||||
float3 worldSpaceSurfaceNormal = 0.0f;
|
||||
float3 surfaceColor = 0.0f;
|
||||
|
||||
if (mask & GEOMETRY_MASK_TRIANGLE) {
|
||||
Triangle triangle;
|
||||
|
||||
float3 objectSpaceSurfaceNormal;
|
||||
if (usePerPrimitiveData) {
|
||||
// Per-primitive data points to data from the specified buffer as was configured in the MTLAccelerationStructureTriangleGeometryDescriptor.
|
||||
triangle = *(const device Triangle*)intersection.primitive_data;
|
||||
} else
|
||||
{
|
||||
// The ray hit a triangle. Look up the corresponding geometry's normal and UV buffers.
|
||||
device TriangleResources & triangleResources = *(device TriangleResources *)((device char *)resources + resourcesStride * geometryIndex);
|
||||
|
||||
triangle.normals[0] = triangleResources.vertexNormals[triangleResources.indices[primitiveIndex * 3 + 0]];
|
||||
triangle.normals[1] = triangleResources.vertexNormals[triangleResources.indices[primitiveIndex * 3 + 1]];
|
||||
triangle.normals[2] = triangleResources.vertexNormals[triangleResources.indices[primitiveIndex * 3 + 2]];
|
||||
|
||||
triangle.colors[0] = triangleResources.vertexColors[triangleResources.indices[primitiveIndex * 3 + 0]];
|
||||
triangle.colors[1] = triangleResources.vertexColors[triangleResources.indices[primitiveIndex * 3 + 1]];
|
||||
triangle.colors[2] = triangleResources.vertexColors[triangleResources.indices[primitiveIndex * 3 + 2]];
|
||||
}
|
||||
|
||||
// Interpolate the vertex normal at the intersection point.
|
||||
objectSpaceSurfaceNormal = interpolateVertexAttribute(triangle.normals, barycentric_coords);
|
||||
|
||||
// Interpolate the vertex color at the intersection point.
|
||||
surfaceColor = interpolateVertexAttribute(triangle.colors, barycentric_coords);
|
||||
|
||||
// Transform the normal from object to world space.
|
||||
worldSpaceSurfaceNormal = normalize(transformDirection(objectSpaceSurfaceNormal, objectToWorldSpaceTransform));
|
||||
}
|
||||
else if (mask & GEOMETRY_MASK_SPHERE) {
|
||||
Sphere sphere;
|
||||
if (usePerPrimitiveData) {
|
||||
// Per-primitive data points to data from the specified buffer as was configured in the MTLAccelerationStructureBoundingBoxGeometryDescriptor.
|
||||
sphere = *(const device Sphere*)intersection.primitive_data;
|
||||
} else
|
||||
{
|
||||
// The ray hit a sphere. Look up the corresponding sphere buffer.
|
||||
device SphereResources & sphereResources = *(device SphereResources *)((device char *)resources + resourcesStride * geometryIndex);
|
||||
sphere = sphereResources.spheres[primitiveIndex];
|
||||
}
|
||||
|
||||
// Transform the sphere's origin from object space to world space.
|
||||
float3 worldSpaceOrigin = transformPoint(sphere.origin, objectToWorldSpaceTransform);
|
||||
|
||||
// Compute the surface normal directly in world space.
|
||||
worldSpaceSurfaceNormal = normalize(worldSpaceIntersectionPoint - worldSpaceOrigin);
|
||||
|
||||
// The sphere is a uniform color, so you don't need to interpolate the color across the surface.
|
||||
surfaceColor = sphere.color;
|
||||
}
|
||||
|
||||
dstTex.write(float4(accumulatedColor, 1.0f), tid);
|
||||
|
||||
// Choose a random light source to sample.
|
||||
float lightSample = halton(offset + uniforms.frameIndex, 2 + bounce * 5 + 0);
|
||||
unsigned int lightIndex = min((unsigned int)(lightSample * uniforms.lightCount), uniforms.lightCount - 1);
|
||||
|
||||
// Choose a random point to sample on the light source.
|
||||
float2 r = float2(halton(offset + uniforms.frameIndex, 2 + bounce * 5 + 1),
|
||||
halton(offset + uniforms.frameIndex, 2 + bounce * 5 + 2));
|
||||
|
||||
float3 worldSpaceLightDirection;
|
||||
float3 lightColor;
|
||||
float lightDistance;
|
||||
|
||||
// Sample the lighting between the intersection point and the point on the area light.
|
||||
sampleAreaLight(areaLights[lightIndex], r, worldSpaceIntersectionPoint, worldSpaceLightDirection,
|
||||
lightColor, lightDistance);
|
||||
|
||||
// Scale the light color by the cosine of the angle between the light direction and
|
||||
// surface normal.
|
||||
lightColor *= saturate(dot(worldSpaceSurfaceNormal, worldSpaceLightDirection));
|
||||
|
||||
// Scale the light color by the number of lights to compensate for the fact that
|
||||
// the sample samples only one light source at random.
|
||||
lightColor *= uniforms.lightCount;
|
||||
|
||||
// Scale the ray color by the color of the surface to simulate the surface absorbing light.
|
||||
color *= surfaceColor;
|
||||
|
||||
// Compute the shadow ray. The shadow ray checks whether the sample position on the
|
||||
// light source is visible from the current intersection point.
|
||||
// If it is, the kernel adds lighting to the output image.
|
||||
struct ray shadowRay;
|
||||
|
||||
// Add a small offset to the intersection point to avoid intersecting the same
|
||||
// triangle again.
|
||||
shadowRay.origin = worldSpaceIntersectionPoint + worldSpaceSurfaceNormal * 1e-3f;
|
||||
|
||||
// Travel toward the light source.
|
||||
shadowRay.direction = worldSpaceLightDirection;
|
||||
|
||||
// Don't overshoot the light source.
|
||||
shadowRay.max_distance = lightDistance - 1e-3f;
|
||||
|
||||
// Shadow rays check only whether there is an object between the intersection point
|
||||
// and the light source. Tell Metal to return after finding any intersection.
|
||||
i.accept_any_intersection(true);
|
||||
|
||||
if (useIntersectionFunctions)
|
||||
intersection = i.intersect(shadowRay, accelerationStructure, RAY_MASK_SHADOW, intersectionFunctionTable);
|
||||
else
|
||||
intersection = i.intersect(shadowRay, accelerationStructure, RAY_MASK_SHADOW);
|
||||
|
||||
// If there was no intersection, then the light source is visible from the original
|
||||
// intersection point. Add the light's contribution to the image.
|
||||
if (intersection.type == intersection_type::none)
|
||||
accumulatedColor += lightColor * color;
|
||||
|
||||
// Choose a random direction to continue the path of the ray. This causes light to
|
||||
// bounce between surfaces. An app might evaluate a more complicated equation to
|
||||
// calculate the amount of light that reflects between intersection points. However,
|
||||
// all the math in this kernel cancels out because this app assumes a simple diffuse
|
||||
// BRDF and samples the rays with a cosine distribution over the hemisphere (importance
|
||||
// sampling). This requires that the kernel only multiply the colors together. This
|
||||
// sampling strategy also reduces the amount of noise in the output image.
|
||||
r = float2(halton(offset + uniforms.frameIndex, 2 + bounce * 5 + 3),
|
||||
halton(offset + uniforms.frameIndex, 2 + bounce * 5 + 4));
|
||||
|
||||
float3 worldSpaceSampleDirection = sampleCosineWeightedHemisphere(r);
|
||||
worldSpaceSampleDirection = alignHemisphereWithNormal(worldSpaceSampleDirection, worldSpaceSurfaceNormal);
|
||||
|
||||
ray.origin = worldSpaceIntersectionPoint + worldSpaceSurfaceNormal * 1e-3f;
|
||||
ray.direction = worldSpaceSampleDirection;
|
||||
}
|
||||
|
||||
// Average this frame's sample with all of the previous frames.
|
||||
if (uniforms.frameIndex > 0) {
|
||||
float3 prevColor = prevTex.read(tid).xyz;
|
||||
prevColor *= uniforms.frameIndex;
|
||||
|
||||
accumulatedColor += prevColor;
|
||||
accumulatedColor /= (uniforms.frameIndex + 1);
|
||||
}
|
||||
|
||||
dstTex.write(float4(accumulatedColor, 1.0f), tid);
|
||||
}
|
||||
|
||||
// Screen filling quad in normalized device coordinates.
|
||||
constant float2 quadVertices[] = {
|
||||
float2(-1, -1),
|
||||
float2(-1, 1),
|
||||
float2( 1, 1),
|
||||
float2(-1, -1),
|
||||
float2( 1, 1),
|
||||
float2( 1, -1)
|
||||
};
|
||||
|
||||
struct CopyVertexOut {
|
||||
float4 position [[position]];
|
||||
float2 uv;
|
||||
};
|
||||
|
||||
// Simple vertex shader that passes through NDC quad positions.
|
||||
vertex CopyVertexOut copyVertex(unsigned short vid [[vertex_id]]) {
|
||||
float2 position = quadVertices[vid];
|
||||
|
||||
CopyVertexOut out;
|
||||
|
||||
out.position = float4(position, 0, 1);
|
||||
out.uv = position * 0.5f + 0.5f;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// Simple fragment shader that copies a texture and applies a simple tonemapping function.
|
||||
fragment float4 copyFragment(CopyVertexOut in [[stage_in]],
|
||||
texture2d<float> tex)
|
||||
{
|
||||
constexpr sampler sam(min_filter::nearest, mag_filter::nearest, mip_filter::none);
|
||||
|
||||
float3 color = tex.sample(sam, in.uv).xyz;
|
||||
|
||||
// Apply a simple tonemapping function to reduce the dynamic range of the
|
||||
// input image into a range which the screen can display.
|
||||
color = color / (1.0f + color);
|
||||
|
||||
return float4(color, 1.0f);
|
||||
}
|
||||
BIN
third-party/vendor/metal/examples/raytracing/shaders.metallib
vendored
Normal file
BIN
third-party/vendor/metal/examples/raytracing/shaders.metallib
vendored
Normal file
Binary file not shown.
75
third-party/vendor/metal/examples/reflection/main.rs
vendored
Normal file
75
third-party/vendor/metal/examples/reflection/main.rs
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use metal::*;
|
||||
use objc::rc::autoreleasepool;
|
||||
|
||||
const PROGRAM: &'static str = r"
|
||||
#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
typedef struct {
|
||||
float2 position;
|
||||
float3 color;
|
||||
} vertex_t;
|
||||
|
||||
struct ColorInOut {
|
||||
float4 position [[position]];
|
||||
float4 color;
|
||||
};
|
||||
|
||||
vertex ColorInOut vs(device vertex_t* vertex_array [[ buffer(0) ]],
|
||||
unsigned int vid [[ vertex_id ]])
|
||||
{
|
||||
ColorInOut out;
|
||||
|
||||
out.position = float4(float2(vertex_array[vid].position), 0.0, 1.0);
|
||||
out.color = float4(float3(vertex_array[vid].color), 1.0);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 ps(ColorInOut in [[stage_in]])
|
||||
{
|
||||
return in.color;
|
||||
};
|
||||
";
|
||||
|
||||
fn main() {
|
||||
autoreleasepool(|| {
|
||||
let device = Device::system_default().expect("no device found");
|
||||
|
||||
let options = CompileOptions::new();
|
||||
let library = device.new_library_with_source(PROGRAM, &options).unwrap();
|
||||
let (vs, ps) = (
|
||||
library.get_function("vs", None).unwrap(),
|
||||
library.get_function("ps", None).unwrap(),
|
||||
);
|
||||
|
||||
let vertex_desc = VertexDescriptor::new();
|
||||
|
||||
let desc = RenderPipelineDescriptor::new();
|
||||
desc.set_vertex_function(Some(&vs));
|
||||
desc.set_fragment_function(Some(&ps));
|
||||
desc.set_vertex_descriptor(Some(vertex_desc));
|
||||
|
||||
println!("{:?}", desc);
|
||||
|
||||
let reflect_options = MTLPipelineOption::ArgumentInfo | MTLPipelineOption::BufferTypeInfo;
|
||||
let (_, reflection) = device
|
||||
.new_render_pipeline_state_with_reflection(&desc, reflect_options)
|
||||
.unwrap();
|
||||
|
||||
println!("Vertex arguments: ");
|
||||
let vertex_arguments = reflection.vertex_arguments();
|
||||
for index in 0..vertex_arguments.count() {
|
||||
let argument = vertex_arguments.object_at(index).unwrap();
|
||||
println!("{:?}", argument);
|
||||
}
|
||||
});
|
||||
}
|
||||
177
third-party/vendor/metal/examples/shader-dylib/main.rs
vendored
Normal file
177
third-party/vendor/metal/examples/shader-dylib/main.rs
vendored
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
use cocoa::{appkit::NSView, base::id as cocoa_id};
|
||||
use core_graphics_types::geometry::CGSize;
|
||||
|
||||
use metal::*;
|
||||
use objc::{rc::autoreleasepool, runtime::YES};
|
||||
|
||||
use winit::{
|
||||
event::{Event, WindowEvent},
|
||||
event_loop::ControlFlow,
|
||||
platform::macos::WindowExtMacOS,
|
||||
};
|
||||
|
||||
use std::mem;
|
||||
|
||||
struct App {
|
||||
pub _device: Device,
|
||||
pub command_queue: CommandQueue,
|
||||
pub layer: MetalLayer,
|
||||
pub image_fill_cps: ComputePipelineState,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
fn select_device() -> Option<Device> {
|
||||
let devices = Device::all();
|
||||
for device in devices {
|
||||
if device.supports_dynamic_libraries() {
|
||||
return Some(device);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
impl App {
|
||||
fn new(window: &winit::window::Window) -> Self {
|
||||
let device = select_device().expect("no device found that supports dynamic libraries");
|
||||
let command_queue = device.new_command_queue();
|
||||
|
||||
let layer = MetalLayer::new();
|
||||
layer.set_device(&device);
|
||||
layer.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
|
||||
layer.set_presents_with_transaction(false);
|
||||
layer.set_framebuffer_only(false);
|
||||
unsafe {
|
||||
let view = window.ns_view() as cocoa_id;
|
||||
view.setWantsLayer(YES);
|
||||
view.setLayer(mem::transmute(layer.as_ref()));
|
||||
}
|
||||
let draw_size = window.inner_size();
|
||||
layer.set_drawable_size(CGSize::new(draw_size.width as f64, draw_size.height as f64));
|
||||
|
||||
// compile dynamic lib shader
|
||||
let dylib_src_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("examples/shader-dylib/test_dylib.metal");
|
||||
let install_path =
|
||||
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("target/test_dylib.metallib");
|
||||
|
||||
let dylib_src = std::fs::read_to_string(dylib_src_path).expect("bad shit");
|
||||
let opts = metal::CompileOptions::new();
|
||||
opts.set_library_type(MTLLibraryType::Dynamic);
|
||||
opts.set_install_name(install_path.to_str().unwrap());
|
||||
|
||||
let lib = device
|
||||
.new_library_with_source(dylib_src.as_str(), &opts)
|
||||
.unwrap();
|
||||
|
||||
// create dylib
|
||||
let dylib = device.new_dynamic_library(&lib).unwrap();
|
||||
dylib.set_label("test_dylib");
|
||||
|
||||
// optional: serialize binary blob that can be loaded later
|
||||
let blob_url = String::from("file://") + install_path.to_str().unwrap();
|
||||
let url = URL::new_with_string(&blob_url);
|
||||
dylib.serialize_to_url(&url).unwrap();
|
||||
|
||||
// create shader that links with dylib
|
||||
let shader_src_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("examples/shader-dylib/test_shader.metal");
|
||||
|
||||
let shader_src = std::fs::read_to_string(shader_src_path).expect("bad shit");
|
||||
let opts = metal::CompileOptions::new();
|
||||
// add dynamic library to link with
|
||||
let libraries = [dylib.as_ref()];
|
||||
opts.set_libraries(&libraries);
|
||||
|
||||
// compile
|
||||
let shader_lib = device
|
||||
.new_library_with_source(shader_src.as_str(), &opts)
|
||||
.unwrap();
|
||||
|
||||
let func = shader_lib.get_function("test_kernel", None).unwrap();
|
||||
|
||||
// create pipeline state
|
||||
// linking occurs here
|
||||
let image_fill_cps = device
|
||||
.new_compute_pipeline_state_with_function(&func)
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
_device: device,
|
||||
command_queue,
|
||||
layer,
|
||||
image_fill_cps,
|
||||
width: draw_size.width,
|
||||
height: draw_size.height,
|
||||
}
|
||||
}
|
||||
|
||||
fn resize(&mut self, width: u32, height: u32) {
|
||||
self.layer
|
||||
.set_drawable_size(CGSize::new(width as f64, height as f64));
|
||||
self.width = width;
|
||||
self.height = height;
|
||||
}
|
||||
|
||||
fn draw(&self) {
|
||||
let drawable = match self.layer.next_drawable() {
|
||||
Some(drawable) => drawable,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let w = self.image_fill_cps.thread_execution_width();
|
||||
let h = self.image_fill_cps.max_total_threads_per_threadgroup() / w;
|
||||
let threads_per_threadgroup = MTLSize::new(w, h, 1);
|
||||
let threads_per_grid = MTLSize::new(self.width as _, self.height as _, 1);
|
||||
|
||||
let command_buffer = self.command_queue.new_command_buffer();
|
||||
|
||||
{
|
||||
let encoder = command_buffer.new_compute_command_encoder();
|
||||
encoder.set_compute_pipeline_state(&self.image_fill_cps);
|
||||
encoder.set_texture(0, Some(&drawable.texture()));
|
||||
encoder.dispatch_threads(threads_per_grid, threads_per_threadgroup);
|
||||
encoder.end_encoding();
|
||||
}
|
||||
|
||||
command_buffer.present_drawable(&drawable);
|
||||
command_buffer.commit();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let events_loop = winit::event_loop::EventLoop::new();
|
||||
let size = winit::dpi::LogicalSize::new(800, 600);
|
||||
|
||||
let window = winit::window::WindowBuilder::new()
|
||||
.with_inner_size(size)
|
||||
.with_title("Metal Shader Dylib Example".to_string())
|
||||
.build(&events_loop)
|
||||
.unwrap();
|
||||
|
||||
let mut app = App::new(&window);
|
||||
|
||||
events_loop.run(move |event, _, control_flow| {
|
||||
autoreleasepool(|| {
|
||||
*control_flow = ControlFlow::Poll;
|
||||
|
||||
match event {
|
||||
Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
||||
WindowEvent::Resized(size) => {
|
||||
app.resize(size.width, size.height);
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
Event::MainEventsCleared => {
|
||||
window.request_redraw();
|
||||
}
|
||||
Event::RedrawRequested(_) => {
|
||||
app.draw();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
8
third-party/vendor/metal/examples/shader-dylib/test_dylib.metal
vendored
Normal file
8
third-party/vendor/metal/examples/shader-dylib/test_dylib.metal
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
float4 get_color_test(float4 inColor)
|
||||
{
|
||||
return float4(inColor.r, inColor.g, inColor.b, 0);
|
||||
}
|
||||
14
third-party/vendor/metal/examples/shader-dylib/test_shader.metal
vendored
Normal file
14
third-party/vendor/metal/examples/shader-dylib/test_shader.metal
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
extern float4 get_color_test(float4 inColor);
|
||||
|
||||
kernel void test_kernel(
|
||||
texture2d<float, access::write> image [[texture(0)]],
|
||||
uint2 coordinates [[thread_position_in_grid]],
|
||||
uint2 size [[threads_per_grid]])
|
||||
{
|
||||
float2 uv = float2(coordinates) / float2(size - 1);
|
||||
image.write(get_color_test(float4(uv, 0.0, 1.0)), coordinates);
|
||||
}
|
||||
11
third-party/vendor/metal/examples/window/README.md
vendored
Normal file
11
third-party/vendor/metal/examples/window/README.md
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
## window
|
||||
|
||||
Renders a spinning triangle to a [winit](https://github.com/rust-windowing/winit) window.
|
||||
|
||||

|
||||
|
||||
## To Run
|
||||
|
||||
```
|
||||
cargo run --example window
|
||||
```
|
||||
261
third-party/vendor/metal/examples/window/main.rs
vendored
Normal file
261
third-party/vendor/metal/examples/window/main.rs
vendored
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
// Copyright 2016 metal-rs developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
extern crate objc;
|
||||
|
||||
use cocoa::{appkit::NSView, base::id as cocoa_id};
|
||||
use core_graphics_types::geometry::CGSize;
|
||||
|
||||
use metal::*;
|
||||
use objc::{rc::autoreleasepool, runtime::YES};
|
||||
use std::mem;
|
||||
use winit::platform::macos::WindowExtMacOS;
|
||||
|
||||
use winit::{
|
||||
event::{Event, WindowEvent},
|
||||
event_loop::ControlFlow,
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
struct Rect {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub w: f32,
|
||||
pub h: f32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct Color {
|
||||
pub r: f32,
|
||||
pub g: f32,
|
||||
pub b: f32,
|
||||
pub a: f32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct ClearRect {
|
||||
pub rect: Rect,
|
||||
pub color: Color,
|
||||
}
|
||||
|
||||
fn prepare_pipeline_state<'a>(
|
||||
device: &DeviceRef,
|
||||
library: &LibraryRef,
|
||||
vertex_shader: &str,
|
||||
fragment_shader: &str,
|
||||
) -> RenderPipelineState {
|
||||
let vert = library.get_function(vertex_shader, None).unwrap();
|
||||
let frag = library.get_function(fragment_shader, None).unwrap();
|
||||
|
||||
let pipeline_state_descriptor = RenderPipelineDescriptor::new();
|
||||
pipeline_state_descriptor.set_vertex_function(Some(&vert));
|
||||
pipeline_state_descriptor.set_fragment_function(Some(&frag));
|
||||
let attachment = pipeline_state_descriptor
|
||||
.color_attachments()
|
||||
.object_at(0)
|
||||
.unwrap();
|
||||
attachment.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
|
||||
|
||||
attachment.set_blending_enabled(true);
|
||||
attachment.set_rgb_blend_operation(metal::MTLBlendOperation::Add);
|
||||
attachment.set_alpha_blend_operation(metal::MTLBlendOperation::Add);
|
||||
attachment.set_source_rgb_blend_factor(metal::MTLBlendFactor::SourceAlpha);
|
||||
attachment.set_source_alpha_blend_factor(metal::MTLBlendFactor::SourceAlpha);
|
||||
attachment.set_destination_rgb_blend_factor(metal::MTLBlendFactor::OneMinusSourceAlpha);
|
||||
attachment.set_destination_alpha_blend_factor(metal::MTLBlendFactor::OneMinusSourceAlpha);
|
||||
|
||||
device
|
||||
.new_render_pipeline_state(&pipeline_state_descriptor)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn prepare_render_pass_descriptor(descriptor: &RenderPassDescriptorRef, texture: &TextureRef) {
|
||||
//descriptor.color_attachments().set_object_at(0, MTLRenderPassColorAttachmentDescriptor::alloc());
|
||||
//let color_attachment: MTLRenderPassColorAttachmentDescriptor = unsafe { msg_send![descriptor.color_attachments().0, _descriptorAtIndex:0] };//descriptor.color_attachments().object_at(0);
|
||||
let color_attachment = descriptor.color_attachments().object_at(0).unwrap();
|
||||
|
||||
color_attachment.set_texture(Some(texture));
|
||||
color_attachment.set_load_action(MTLLoadAction::Clear);
|
||||
color_attachment.set_clear_color(MTLClearColor::new(0.2, 0.2, 0.25, 1.0));
|
||||
color_attachment.set_store_action(MTLStoreAction::Store);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let events_loop = winit::event_loop::EventLoop::new();
|
||||
let size = winit::dpi::LogicalSize::new(800, 600);
|
||||
|
||||
let window = winit::window::WindowBuilder::new()
|
||||
.with_inner_size(size)
|
||||
.with_title("Metal Window Example".to_string())
|
||||
.build(&events_loop)
|
||||
.unwrap();
|
||||
|
||||
let device = Device::system_default().expect("no device found");
|
||||
|
||||
let layer = MetalLayer::new();
|
||||
layer.set_device(&device);
|
||||
layer.set_pixel_format(MTLPixelFormat::BGRA8Unorm);
|
||||
layer.set_presents_with_transaction(false);
|
||||
|
||||
unsafe {
|
||||
let view = window.ns_view() as cocoa_id;
|
||||
view.setWantsLayer(YES);
|
||||
view.setLayer(mem::transmute(layer.as_ref()));
|
||||
}
|
||||
|
||||
let draw_size = window.inner_size();
|
||||
layer.set_drawable_size(CGSize::new(draw_size.width as f64, draw_size.height as f64));
|
||||
|
||||
let library_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("examples/window/shaders.metallib");
|
||||
|
||||
let library = device.new_library_with_file(library_path).unwrap();
|
||||
let triangle_pipeline_state =
|
||||
prepare_pipeline_state(&device, &library, "triangle_vertex", "triangle_fragment");
|
||||
let clear_rect_pipeline_state = prepare_pipeline_state(
|
||||
&device,
|
||||
&library,
|
||||
"clear_rect_vertex",
|
||||
"clear_rect_fragment",
|
||||
);
|
||||
|
||||
let command_queue = device.new_command_queue();
|
||||
//let nc: () = msg_send![command_queue.0, setExecutionEnabled:true];
|
||||
|
||||
let vbuf = {
|
||||
let vertex_data = [
|
||||
0.0f32, 0.5, 1.0, 0.0, 0.0, -0.5, -0.5, 0.0, 1.0, 0.0, 0.5, 0.5, 0.0, 0.0, 1.0,
|
||||
];
|
||||
|
||||
device.new_buffer_with_data(
|
||||
vertex_data.as_ptr() as *const _,
|
||||
(vertex_data.len() * mem::size_of::<f32>()) as u64,
|
||||
MTLResourceOptions::CPUCacheModeDefaultCache | MTLResourceOptions::StorageModeManaged,
|
||||
)
|
||||
};
|
||||
|
||||
let mut r = 0.0f32;
|
||||
|
||||
let clear_rect = vec![ClearRect {
|
||||
rect: Rect {
|
||||
x: -1.0,
|
||||
y: -1.0,
|
||||
w: 2.0,
|
||||
h: 2.0,
|
||||
},
|
||||
color: Color {
|
||||
r: 0.5,
|
||||
g: 0.8,
|
||||
b: 0.5,
|
||||
a: 1.0,
|
||||
},
|
||||
}];
|
||||
|
||||
let clear_rect_buffer = device.new_buffer_with_data(
|
||||
clear_rect.as_ptr() as *const _,
|
||||
mem::size_of::<ClearRect>() as u64,
|
||||
MTLResourceOptions::CPUCacheModeDefaultCache | MTLResourceOptions::StorageModeManaged,
|
||||
);
|
||||
|
||||
events_loop.run(move |event, _, control_flow| {
|
||||
autoreleasepool(|| {
|
||||
*control_flow = ControlFlow::Poll;
|
||||
|
||||
match event {
|
||||
Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
||||
WindowEvent::Resized(size) => {
|
||||
layer.set_drawable_size(CGSize::new(size.width as f64, size.height as f64));
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
Event::MainEventsCleared => {
|
||||
window.request_redraw();
|
||||
}
|
||||
Event::RedrawRequested(_) => {
|
||||
let p = vbuf.contents();
|
||||
let vertex_data = [
|
||||
0.0f32,
|
||||
0.5,
|
||||
1.0,
|
||||
0.0,
|
||||
0.0,
|
||||
-0.5 + (r.cos() / 2. + 0.5),
|
||||
-0.5,
|
||||
0.0,
|
||||
1.0,
|
||||
0.0,
|
||||
0.5 - (r.cos() / 2. + 0.5),
|
||||
-0.5,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
];
|
||||
|
||||
unsafe {
|
||||
std::ptr::copy(
|
||||
vertex_data.as_ptr(),
|
||||
p as *mut f32,
|
||||
(vertex_data.len() * mem::size_of::<f32>()) as usize,
|
||||
);
|
||||
}
|
||||
|
||||
vbuf.did_modify_range(crate::NSRange::new(
|
||||
0 as u64,
|
||||
(vertex_data.len() * mem::size_of::<f32>()) as u64,
|
||||
));
|
||||
|
||||
let drawable = match layer.next_drawable() {
|
||||
Some(drawable) => drawable,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let render_pass_descriptor = RenderPassDescriptor::new();
|
||||
|
||||
prepare_render_pass_descriptor(&render_pass_descriptor, drawable.texture());
|
||||
|
||||
let command_buffer = command_queue.new_command_buffer();
|
||||
let encoder =
|
||||
command_buffer.new_render_command_encoder(&render_pass_descriptor);
|
||||
|
||||
encoder.set_scissor_rect(MTLScissorRect {
|
||||
x: 20,
|
||||
y: 20,
|
||||
width: 100,
|
||||
height: 100,
|
||||
});
|
||||
encoder.set_render_pipeline_state(&clear_rect_pipeline_state);
|
||||
encoder.set_vertex_buffer(0, Some(&clear_rect_buffer), 0);
|
||||
encoder.draw_primitives_instanced(
|
||||
metal::MTLPrimitiveType::TriangleStrip,
|
||||
0,
|
||||
4,
|
||||
1,
|
||||
);
|
||||
let physical_size = window.inner_size();
|
||||
encoder.set_scissor_rect(MTLScissorRect {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: physical_size.width as _,
|
||||
height: physical_size.height as _,
|
||||
});
|
||||
|
||||
encoder.set_render_pipeline_state(&triangle_pipeline_state);
|
||||
encoder.set_vertex_buffer(0, Some(&vbuf), 0);
|
||||
encoder.draw_primitives(MTLPrimitiveType::Triangle, 0, 3);
|
||||
encoder.end_encoding();
|
||||
|
||||
command_buffer.present_drawable(&drawable);
|
||||
command_buffer.commit();
|
||||
|
||||
r += 0.01f32;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
BIN
third-party/vendor/metal/examples/window/screenshot.png
vendored
Normal file
BIN
third-party/vendor/metal/examples/window/screenshot.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
97
third-party/vendor/metal/examples/window/shaders.metal
vendored
Normal file
97
third-party/vendor/metal/examples/window/shaders.metal
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
typedef struct {
|
||||
packed_float2 position;
|
||||
packed_float3 color;
|
||||
} vertex_t;
|
||||
|
||||
struct ColorInOut {
|
||||
float4 position [[position]];
|
||||
float4 color;
|
||||
};
|
||||
// vertex shader function
|
||||
vertex ColorInOut triangle_vertex(const device vertex_t* vertex_array [[ buffer(0) ]],
|
||||
unsigned int vid [[ vertex_id ]])
|
||||
{
|
||||
ColorInOut out;
|
||||
|
||||
auto device const &v = vertex_array[vid];
|
||||
out.position = float4(v.position.x, v.position.y, 0.0, 1.0);
|
||||
out.color = float4(v.color.x, v.color.y, v.color.z, 0.2);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// fragment shader function
|
||||
fragment float4 triangle_fragment(ColorInOut in [[stage_in]])
|
||||
{
|
||||
return in.color;
|
||||
};
|
||||
|
||||
|
||||
struct Rect {
|
||||
float x;
|
||||
float y;
|
||||
float w;
|
||||
float h;
|
||||
};
|
||||
|
||||
struct Color {
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
};
|
||||
|
||||
struct ClearRect {
|
||||
Rect rect;
|
||||
Color color;
|
||||
};
|
||||
|
||||
float2 rect_vert(
|
||||
Rect rect,
|
||||
uint vid
|
||||
) {
|
||||
float2 pos;
|
||||
|
||||
float left = rect.x;
|
||||
float right = rect.x + rect.w;
|
||||
float bottom = rect.y;
|
||||
float top = rect.y + rect.h;
|
||||
|
||||
switch (vid) {
|
||||
case 0:
|
||||
pos = float2(right, top);
|
||||
break;
|
||||
case 1:
|
||||
pos = float2(left, top);
|
||||
break;
|
||||
case 2:
|
||||
pos = float2(right, bottom);
|
||||
break;
|
||||
case 3:
|
||||
pos = float2(left, bottom);
|
||||
break;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
vertex ColorInOut clear_rect_vertex(
|
||||
const device ClearRect *clear_rect [[ buffer(0) ]],
|
||||
unsigned int vid [[ vertex_id ]]
|
||||
) {
|
||||
ColorInOut out;
|
||||
float4 pos = float4(rect_vert(clear_rect->rect, vid), 0, 1);
|
||||
auto col = clear_rect->color;
|
||||
|
||||
out.position = pos;
|
||||
out.color = float4(col.r, col.g, col.b, col.a);
|
||||
return out;
|
||||
}
|
||||
|
||||
fragment float4 clear_rect_fragment(ColorInOut in [[stage_in]])
|
||||
{
|
||||
return in.color;
|
||||
};
|
||||
BIN
third-party/vendor/metal/examples/window/shaders.metallib
vendored
Normal file
BIN
third-party/vendor/metal/examples/window/shaders.metallib
vendored
Normal file
Binary file not shown.
348
third-party/vendor/metal/src/accelerator_structure.rs
vendored
Normal file
348
third-party/vendor/metal/src/accelerator_structure.rs
vendored
Normal file
|
|
@ -0,0 +1,348 @@
|
|||
// Copyright 2023 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
|
||||
bitflags! {
|
||||
#[derive(Copy, Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct MTLAccelerationStructureInstanceOptions: u32 {
|
||||
const None = 0;
|
||||
const DisableTriangleCulling = (1 << 0);
|
||||
const TriangleFrontFacingWindingCounterClockwise = (1 << 1);
|
||||
const Opaque = (1 << 2);
|
||||
const NonOpaque = (1 << 3);
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlaccelerationstructureinstancedescriptortype>
|
||||
#[repr(u64)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub enum MTLAccelerationStructureInstanceDescriptorType {
|
||||
Default = 0,
|
||||
UserID = 1,
|
||||
Motion = 2,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct MTLAccelerationStructureInstanceDescriptor {
|
||||
pub transformation_matrix: [[f32; 3]; 4],
|
||||
pub options: MTLAccelerationStructureInstanceOptions,
|
||||
pub mask: u32,
|
||||
pub intersection_function_table_offset: u32,
|
||||
pub acceleration_structure_index: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct MTLAccelerationStructureUserIDInstanceDescriptor {
|
||||
pub transformation_matrix: [[f32; 3]; 4],
|
||||
pub options: MTLAccelerationStructureInstanceOptions,
|
||||
pub mask: u32,
|
||||
pub intersection_function_table_offset: u32,
|
||||
pub acceleration_structure_index: u32,
|
||||
pub user_id: u32,
|
||||
}
|
||||
|
||||
pub enum MTLAccelerationStructureDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLAccelerationStructureDescriptor;
|
||||
pub struct AccelerationStructureDescriptor;
|
||||
type ParentType = NsObject;
|
||||
}
|
||||
|
||||
pub enum MTLPrimitiveAccelerationStructureDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLPrimitiveAccelerationStructureDescriptor;
|
||||
pub struct PrimitiveAccelerationStructureDescriptor;
|
||||
type ParentType = AccelerationStructureDescriptor;
|
||||
}
|
||||
|
||||
impl PrimitiveAccelerationStructureDescriptor {
|
||||
pub fn descriptor() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLPrimitiveAccelerationStructureDescriptor);
|
||||
msg_send![class, descriptor]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PrimitiveAccelerationStructureDescriptorRef {
|
||||
pub fn set_geometry_descriptors(
|
||||
&self,
|
||||
descriptors: &ArrayRef<AccelerationStructureGeometryDescriptor>,
|
||||
) {
|
||||
unsafe { msg_send![self, setGeometryDescriptors: descriptors] }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MTLAccelerationStructure {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLAccelerationStructure;
|
||||
pub struct AccelerationStructure;
|
||||
type ParentType = Resource;
|
||||
}
|
||||
|
||||
pub enum MTLAccelerationStructureGeometryDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLAccelerationStructureGeometryDescriptor;
|
||||
pub struct AccelerationStructureGeometryDescriptor;
|
||||
type ParentType = NsObject;
|
||||
}
|
||||
|
||||
impl AccelerationStructureGeometryDescriptorRef {
|
||||
pub fn set_opaque(&self, opaque: bool) {
|
||||
unsafe { msg_send![self, setOpaque: opaque] }
|
||||
}
|
||||
pub fn set_primitive_data_buffer(&self, buffer: Option<&BufferRef>) {
|
||||
unsafe { msg_send![self, setPrimitiveDataBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn set_primitive_data_stride(&self, stride: NSUInteger) {
|
||||
unsafe { msg_send![self, setPrimitiveDataStride: stride] }
|
||||
}
|
||||
|
||||
pub fn set_primitive_data_element_size(&self, size: NSUInteger) {
|
||||
unsafe { msg_send![self, setPrimitiveDataElementSize: size] }
|
||||
}
|
||||
|
||||
pub fn set_intersection_function_table_offset(&self, offset: NSUInteger) {
|
||||
unsafe { msg_send![self, setIntersectionFunctionTableOffset: offset] }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MTLAccelerationStructureTriangleGeometryDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLAccelerationStructureTriangleGeometryDescriptor;
|
||||
pub struct AccelerationStructureTriangleGeometryDescriptor;
|
||||
type ParentType = AccelerationStructureGeometryDescriptor;
|
||||
}
|
||||
|
||||
impl AccelerationStructureTriangleGeometryDescriptor {
|
||||
pub fn descriptor() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLAccelerationStructureTriangleGeometryDescriptor);
|
||||
msg_send![class, descriptor]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AccelerationStructureTriangleGeometryDescriptorRef {
|
||||
pub fn set_index_buffer(&self, buffer: Option<&BufferRef>) {
|
||||
unsafe { msg_send![self, setIndexBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn set_index_buffer_offset(&self, offset: NSUInteger) {
|
||||
unsafe { msg_send![self, setIndexBufferOffset: offset] }
|
||||
}
|
||||
|
||||
pub fn set_index_type(&self, t: MTLIndexType) {
|
||||
unsafe { msg_send![self, setIndexType: t] }
|
||||
}
|
||||
|
||||
pub fn set_vertex_buffer(&self, buffer: Option<&BufferRef>) {
|
||||
unsafe { msg_send![self, setVertexBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn set_vertex_buffer_offset(&self, offset: NSUInteger) {
|
||||
unsafe { msg_send![self, setVertexBufferOffset: offset] }
|
||||
}
|
||||
|
||||
pub fn set_vertex_stride(&self, stride: NSUInteger) {
|
||||
unsafe { msg_send![self, setVertexStride: stride] }
|
||||
}
|
||||
|
||||
pub fn set_triangle_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setTriangleCount: count] }
|
||||
}
|
||||
|
||||
pub fn set_vertex_format(&self, format: MTLAttributeFormat) {
|
||||
unsafe { msg_send![self, setVertexFormat: format] }
|
||||
}
|
||||
|
||||
pub fn set_transformation_matrix_buffer(&self, buffer: Option<&BufferRef>) {
|
||||
unsafe { msg_send![self, setTransformationMatrixBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn set_transformation_matrix_buffer_offset(&self, offset: NSUInteger) {
|
||||
unsafe { msg_send![self, setTransformationMatrixBufferOffset: offset] }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MTLAccelerationStructureBoundingBoxGeometryDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLAccelerationStructureBoundingBoxGeometryDescriptor;
|
||||
pub struct AccelerationStructureBoundingBoxGeometryDescriptor;
|
||||
type ParentType = AccelerationStructureGeometryDescriptor;
|
||||
}
|
||||
|
||||
impl AccelerationStructureBoundingBoxGeometryDescriptor {
|
||||
pub fn descriptor() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLAccelerationStructureBoundingBoxGeometryDescriptor);
|
||||
msg_send![class, descriptor]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AccelerationStructureBoundingBoxGeometryDescriptorRef {
|
||||
pub fn set_bounding_box_buffer(&self, buffer: Option<&BufferRef>) {
|
||||
unsafe { msg_send![self, setBoundingBoxBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn set_bounding_box_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setBoundingBoxCount: count] }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MTLInstanceAccelerationStructureDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLInstanceAccelerationStructureDescriptor;
|
||||
pub struct InstanceAccelerationStructureDescriptor;
|
||||
type ParentType = AccelerationStructureDescriptor;
|
||||
}
|
||||
|
||||
impl InstanceAccelerationStructureDescriptor {
|
||||
pub fn descriptor() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLInstanceAccelerationStructureDescriptor);
|
||||
msg_send![class, descriptor]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InstanceAccelerationStructureDescriptorRef {
|
||||
pub fn set_instance_descriptor_type(&self, ty: MTLAccelerationStructureInstanceDescriptorType) {
|
||||
unsafe { msg_send![self, setInstanceDescriptorType: ty] }
|
||||
}
|
||||
|
||||
pub fn set_instanced_acceleration_structures(
|
||||
&self,
|
||||
instances: &ArrayRef<AccelerationStructure>,
|
||||
) {
|
||||
unsafe { msg_send![self, setInstancedAccelerationStructures: instances] }
|
||||
}
|
||||
|
||||
pub fn set_instance_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setInstanceCount: count] }
|
||||
}
|
||||
|
||||
pub fn set_instance_descriptor_buffer(&self, buffer: &BufferRef) {
|
||||
unsafe { msg_send![self, setInstanceDescriptorBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn set_instance_descriptor_buffer_offset(&self, offset: NSUInteger) {
|
||||
unsafe { msg_send![self, setInstanceDescriptorBufferOffset: offset] }
|
||||
}
|
||||
|
||||
pub fn set_instance_descriptor_stride(&self, stride: NSUInteger) {
|
||||
unsafe { msg_send![self, setInstanceDescriptorStride: stride] }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MTLAccelerationStructureCommandEncoder {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLAccelerationStructureCommandEncoder;
|
||||
pub struct AccelerationStructureCommandEncoder;
|
||||
type ParentType = CommandEncoder;
|
||||
}
|
||||
|
||||
impl AccelerationStructureCommandEncoderRef {
|
||||
pub fn build_acceleration_structure(
|
||||
&self,
|
||||
acceleration_structure: &self::AccelerationStructureRef,
|
||||
descriptor: &self::AccelerationStructureDescriptorRef,
|
||||
scratch_buffer: &BufferRef,
|
||||
scratch_buffer_offset: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
buildAccelerationStructure: acceleration_structure
|
||||
descriptor: descriptor
|
||||
scratchBuffer: scratch_buffer
|
||||
scratchBufferOffset: scratch_buffer_offset]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_compacted_acceleration_structure_size(
|
||||
&self,
|
||||
acceleration_structure: &AccelerationStructureRef,
|
||||
to_buffer: &BufferRef,
|
||||
offset: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
writeCompactedAccelerationStructureSize: acceleration_structure
|
||||
toBuffer: to_buffer
|
||||
offset: offset
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_and_compact_acceleration_structure(
|
||||
&self,
|
||||
source: &AccelerationStructureRef,
|
||||
destination: &AccelerationStructureRef,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
copyAndCompactAccelerationStructure: source
|
||||
toAccelerationStructure: destination
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MTLIntersectionFunctionTableDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLIntersectionFunctionTableDescriptor;
|
||||
pub struct IntersectionFunctionTableDescriptor;
|
||||
type ParentType = NsObject;
|
||||
}
|
||||
|
||||
impl IntersectionFunctionTableDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLIntersectionFunctionTableDescriptor);
|
||||
let this: *mut <Self as ForeignType>::CType = msg_send![class, alloc];
|
||||
msg_send![this, init]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntersectionFunctionTableDescriptorRef {
|
||||
pub fn set_function_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setFunctionCount: count] }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MTLIntersectionFunctionTable {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLIntersectionFunctionTable;
|
||||
pub struct IntersectionFunctionTable;
|
||||
type ParentType = Resource;
|
||||
}
|
||||
|
||||
impl IntersectionFunctionTableRef {
|
||||
pub fn set_function(&self, function: &FunctionHandleRef, index: NSUInteger) {
|
||||
unsafe { msg_send![self, setFunction: function atIndex: index] }
|
||||
}
|
||||
}
|
||||
342
third-party/vendor/metal/src/argument.rs
vendored
Normal file
342
third-party/vendor/metal/src/argument.rs
vendored
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
// Copyright 2017 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::{MTLTextureType, NSUInteger};
|
||||
use objc::runtime::{NO, YES};
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtldatatype>
|
||||
#[repr(u64)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLDataType {
|
||||
None = 0,
|
||||
|
||||
Struct = 1,
|
||||
Array = 2,
|
||||
|
||||
Float = 3,
|
||||
Float2 = 4,
|
||||
Float3 = 5,
|
||||
Float4 = 6,
|
||||
|
||||
Float2x2 = 7,
|
||||
Float2x3 = 8,
|
||||
Float2x4 = 9,
|
||||
|
||||
Float3x2 = 10,
|
||||
Float3x3 = 11,
|
||||
Float3x4 = 12,
|
||||
|
||||
Float4x2 = 13,
|
||||
Float4x3 = 14,
|
||||
Float4x4 = 15,
|
||||
|
||||
Half = 16,
|
||||
Half2 = 17,
|
||||
Half3 = 18,
|
||||
Half4 = 19,
|
||||
|
||||
Half2x2 = 20,
|
||||
Half2x3 = 21,
|
||||
Half2x4 = 22,
|
||||
|
||||
Half3x2 = 23,
|
||||
Half3x3 = 24,
|
||||
Half3x4 = 25,
|
||||
|
||||
Half4x2 = 26,
|
||||
Half4x3 = 27,
|
||||
Half4x4 = 28,
|
||||
|
||||
Int = 29,
|
||||
Int2 = 30,
|
||||
Int3 = 31,
|
||||
Int4 = 32,
|
||||
|
||||
UInt = 33,
|
||||
UInt2 = 34,
|
||||
UInt3 = 35,
|
||||
UInt4 = 36,
|
||||
|
||||
Short = 37,
|
||||
Short2 = 38,
|
||||
Short3 = 39,
|
||||
Short4 = 40,
|
||||
|
||||
UShort = 41,
|
||||
UShort2 = 42,
|
||||
UShort3 = 43,
|
||||
UShort4 = 44,
|
||||
|
||||
Char = 45,
|
||||
Char2 = 46,
|
||||
Char3 = 47,
|
||||
Char4 = 48,
|
||||
|
||||
UChar = 49,
|
||||
UChar2 = 50,
|
||||
UChar3 = 51,
|
||||
UChar4 = 52,
|
||||
|
||||
Bool = 53,
|
||||
Bool2 = 54,
|
||||
Bool3 = 55,
|
||||
Bool4 = 56,
|
||||
|
||||
Texture = 58,
|
||||
Sampler = 59,
|
||||
Pointer = 60,
|
||||
R8Unorm = 62,
|
||||
R8Snorm = 63,
|
||||
R16Unorm = 64,
|
||||
R16Snorm = 65,
|
||||
RG8Unorm = 66,
|
||||
RG8Snorm = 67,
|
||||
RG16Unorm = 68,
|
||||
RG16Snorm = 69,
|
||||
RGBA8Unorm = 70,
|
||||
RGBA8Unorm_sRGB = 71,
|
||||
RGBA8Snorm = 72,
|
||||
RGBA16Unorm = 73,
|
||||
RGBA16Snorm = 74,
|
||||
RGB10A2Unorm = 75,
|
||||
RG11B10Float = 76,
|
||||
RGB9E5Float = 77,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlargumenttype>
|
||||
#[repr(u64)]
|
||||
#[deprecated(
|
||||
note = "Since: iOS 8.0–16.0, iPadOS 8.0–16.0, macOS 10.11–13.0, Mac Catalyst 13.1–16.0, tvOS 9.0–16.0"
|
||||
)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLArgumentType {
|
||||
Buffer = 0,
|
||||
ThreadgroupMemory = 1,
|
||||
Texture = 2,
|
||||
Sampler = 3,
|
||||
ImageblockData = 16,
|
||||
Imageblock = 17,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlargumentaccess>
|
||||
#[repr(u64)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLArgumentAccess {
|
||||
ReadOnly = 0,
|
||||
ReadWrite = 1,
|
||||
WriteOnly = 2,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlstructmember>
|
||||
pub enum MTLStructMember {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLStructMember;
|
||||
pub struct StructMember;
|
||||
}
|
||||
|
||||
impl StructMemberRef {
|
||||
pub fn name(&self) -> &str {
|
||||
unsafe {
|
||||
let name = msg_send![self, name];
|
||||
crate::nsstring_as_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offset(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, offset] }
|
||||
}
|
||||
|
||||
pub fn data_type(&self) -> MTLDataType {
|
||||
unsafe { msg_send![self, dataType] }
|
||||
}
|
||||
|
||||
pub fn struct_type(&self) -> MTLStructType {
|
||||
unsafe { msg_send![self, structType] }
|
||||
}
|
||||
|
||||
pub fn array_type(&self) -> MTLArrayType {
|
||||
unsafe { msg_send![self, arrayType] }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum MTLStructMemberArray {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLStructMemberArray;
|
||||
pub struct StructMemberArray;
|
||||
}
|
||||
|
||||
impl StructMemberArrayRef {
|
||||
pub fn object_at(&self, index: NSUInteger) -> Option<&StructMemberRef> {
|
||||
unsafe { msg_send![self, objectAtIndexedSubscript: index] }
|
||||
}
|
||||
|
||||
pub fn count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, count] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlstructtype>
|
||||
pub enum MTLStructType {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLStructType;
|
||||
pub struct StructType;
|
||||
}
|
||||
|
||||
impl StructTypeRef {
|
||||
pub fn members(&self) -> &StructMemberArrayRef {
|
||||
unsafe { msg_send![self, members] }
|
||||
}
|
||||
|
||||
pub fn member_from_name(&self, name: &str) -> Option<&StructMemberRef> {
|
||||
let nsname = crate::nsstring_from_str(name);
|
||||
|
||||
unsafe { msg_send![self, memberByName: nsname] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlarraytype>
|
||||
pub enum MTLArrayType {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLArrayType;
|
||||
pub struct ArrayType;
|
||||
}
|
||||
|
||||
impl ArrayTypeRef {
|
||||
pub fn array_length(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, arrayLength] }
|
||||
}
|
||||
|
||||
pub fn stride(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, stride] }
|
||||
}
|
||||
|
||||
pub fn element_type(&self) -> MTLDataType {
|
||||
unsafe { msg_send![self, elementType] }
|
||||
}
|
||||
|
||||
pub fn element_struct_type(&self) -> MTLStructType {
|
||||
unsafe { msg_send![self, elementStructType] }
|
||||
}
|
||||
|
||||
pub fn element_array_type(&self) -> MTLArrayType {
|
||||
unsafe { msg_send![self, elementArrayType] }
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://developer.apple.com/documentation/metal/mtlargument>
|
||||
#[deprecated(
|
||||
note = "Since iOS 8.0–16.0, iPadOS 8.0–16.0, macOS 10.11–13.0, Mac Catalyst 13.1–16.0, tvOS 9.0–16.0"
|
||||
)]
|
||||
pub enum MTLArgument {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLArgument;
|
||||
pub struct Argument;
|
||||
}
|
||||
|
||||
impl ArgumentRef {
|
||||
pub fn name(&self) -> &str {
|
||||
unsafe {
|
||||
let name = msg_send![self, name];
|
||||
crate::nsstring_as_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_(&self) -> MTLArgumentType {
|
||||
unsafe { msg_send![self, type] }
|
||||
}
|
||||
|
||||
pub fn access(&self) -> MTLArgumentAccess {
|
||||
unsafe { msg_send![self, access] }
|
||||
}
|
||||
|
||||
pub fn index(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, index] }
|
||||
}
|
||||
|
||||
pub fn is_active(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isActive] }
|
||||
}
|
||||
|
||||
pub fn buffer_alignment(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, bufferAlignment] }
|
||||
}
|
||||
|
||||
pub fn buffer_data_size(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, bufferDataSize] }
|
||||
}
|
||||
|
||||
pub fn buffer_data_type(&self) -> MTLDataType {
|
||||
unsafe { msg_send![self, bufferDataType] }
|
||||
}
|
||||
|
||||
pub fn buffer_struct_type(&self) -> &StructTypeRef {
|
||||
unsafe { msg_send![self, bufferStructType] }
|
||||
}
|
||||
|
||||
pub fn threadgroup_memory_alignment(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, threadgroupMemoryAlignment] }
|
||||
}
|
||||
|
||||
pub fn threadgroup_memory_data_size(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, threadgroupMemoryDataSize] }
|
||||
}
|
||||
|
||||
pub fn texture_type(&self) -> MTLTextureType {
|
||||
unsafe { msg_send![self, textureType] }
|
||||
}
|
||||
|
||||
pub fn texture_data_type(&self) -> MTLDataType {
|
||||
unsafe { msg_send![self, textureDataType] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlargumentdescriptor>
|
||||
pub enum MTLArgumentDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLArgumentDescriptor;
|
||||
pub struct ArgumentDescriptor;
|
||||
}
|
||||
|
||||
impl ArgumentDescriptor {
|
||||
pub fn new<'a>() -> &'a ArgumentDescriptorRef {
|
||||
unsafe {
|
||||
let class = class!(MTLArgumentDescriptor);
|
||||
msg_send![class, argumentDescriptor]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ArgumentDescriptorRef {
|
||||
pub fn set_data_type(&self, ty: MTLDataType) {
|
||||
unsafe { msg_send![self, setDataType: ty] }
|
||||
}
|
||||
|
||||
pub fn set_index(&self, index: NSUInteger) {
|
||||
unsafe { msg_send![self, setIndex: index] }
|
||||
}
|
||||
|
||||
pub fn set_access(&self, access: MTLArgumentAccess) {
|
||||
unsafe { msg_send![self, setAccess: access] }
|
||||
}
|
||||
|
||||
pub fn set_array_length(&self, length: NSUInteger) {
|
||||
unsafe { msg_send![self, setArrayLength: length] }
|
||||
}
|
||||
|
||||
pub fn set_texture_type(&self, ty: MTLTextureType) {
|
||||
unsafe { msg_send![self, setTextureType: ty] }
|
||||
}
|
||||
}
|
||||
71
third-party/vendor/metal/src/buffer.rs
vendored
Normal file
71
third-party/vendor/metal/src/buffer.rs
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlbuffer>
|
||||
pub enum MTLBuffer {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLBuffer;
|
||||
pub struct Buffer;
|
||||
type ParentType = Resource;
|
||||
}
|
||||
|
||||
impl BufferRef {
|
||||
pub fn length(&self) -> u64 {
|
||||
unsafe { msg_send![self, length] }
|
||||
}
|
||||
|
||||
pub fn contents(&self) -> *mut std::ffi::c_void {
|
||||
unsafe { msg_send![self, contents] }
|
||||
}
|
||||
|
||||
pub fn did_modify_range(&self, range: crate::NSRange) {
|
||||
unsafe { msg_send![self, didModifyRange: range] }
|
||||
}
|
||||
|
||||
pub fn new_texture_with_descriptor(
|
||||
&self,
|
||||
descriptor: &TextureDescriptorRef,
|
||||
offset: u64,
|
||||
bytes_per_row: u64,
|
||||
) -> Texture {
|
||||
unsafe {
|
||||
msg_send![self,
|
||||
newTextureWithDescriptor:descriptor
|
||||
offset:offset
|
||||
bytesPerRow:bytes_per_row
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on macos(10.15), NOT available on (ios)
|
||||
pub fn remote_storage_buffer(&self) -> &BufferRef {
|
||||
unsafe { msg_send![self, remoteStorageBuffer] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.15), NOT available on (ios)
|
||||
pub fn new_remote_buffer_view_for_device(&self, device: &DeviceRef) -> Buffer {
|
||||
unsafe { msg_send![self, newRemoteBufferViewForDevice: device] }
|
||||
}
|
||||
|
||||
pub fn add_debug_marker(&self, name: &str, range: crate::NSRange) {
|
||||
unsafe {
|
||||
let name = crate::nsstring_from_str(name);
|
||||
msg_send![self, addDebugMarker:name range:range]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_all_debug_markers(&self) {
|
||||
unsafe { msg_send![self, removeAllDebugMarkers] }
|
||||
}
|
||||
|
||||
pub fn gpu_address(&self) -> u64 {
|
||||
unsafe { msg_send![self, gpuAddress] }
|
||||
}
|
||||
}
|
||||
76
third-party/vendor/metal/src/capturedescriptor.rs
vendored
Normal file
76
third-party/vendor/metal/src/capturedescriptor.rs
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright 2020 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcapturedestination?language=objc>
|
||||
#[repr(u64)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLCaptureDestination {
|
||||
DeveloperTools = 1,
|
||||
GpuTraceDocument = 2,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcapturedescriptor>
|
||||
pub enum MTLCaptureDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLCaptureDescriptor;
|
||||
pub struct CaptureDescriptor;
|
||||
}
|
||||
|
||||
impl CaptureDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLCaptureDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CaptureDescriptorRef {
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcapturedescriptor/3237248-captureobject>
|
||||
pub fn set_capture_device(&self, device: &DeviceRef) {
|
||||
unsafe { msg_send![self, setCaptureObject: device] }
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcapturedescriptor/3237248-captureobject>
|
||||
pub fn set_capture_scope(&self, scope: &CaptureScopeRef) {
|
||||
unsafe { msg_send![self, setCaptureObject: scope] }
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcapturedescriptor/3237248-captureobject>
|
||||
pub fn set_capture_command_queue(&self, command_queue: &CommandQueueRef) {
|
||||
unsafe { msg_send![self, setCaptureObject: command_queue] }
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcapturedescriptor/3237250-outputurl>
|
||||
pub fn output_url(&self) -> &Path {
|
||||
let url: &URLRef = unsafe { msg_send![self, outputURL] };
|
||||
Path::new(url.path())
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcapturedescriptor/3237250-outputurl>
|
||||
pub fn set_output_url<P: AsRef<Path>>(&self, output_url: P) {
|
||||
let output_url_string = String::from("file://") + output_url.as_ref().to_str().unwrap();
|
||||
let output_url = URL::new_with_string(&output_url_string);
|
||||
unsafe { msg_send![self, setOutputURL: output_url] }
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcapturedescriptor?language=objc>
|
||||
pub fn destination(&self) -> MTLCaptureDestination {
|
||||
unsafe { msg_send![self, destination] }
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcapturedescriptor?language=objc>
|
||||
pub fn set_destination(&self, destination: MTLCaptureDestination) {
|
||||
unsafe { msg_send![self, setDestination: destination] }
|
||||
}
|
||||
}
|
||||
113
third-party/vendor/metal/src/capturemanager.rs
vendored
Normal file
113
third-party/vendor/metal/src/capturemanager.rs
vendored
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright 2018 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
use std::ffi::CStr;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcapturescope>
|
||||
pub enum MTLCaptureScope {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLCaptureScope;
|
||||
pub struct CaptureScope;
|
||||
}
|
||||
|
||||
impl CaptureScopeRef {
|
||||
pub fn begin_scope(&self) {
|
||||
unsafe { msg_send![self, beginScope] }
|
||||
}
|
||||
|
||||
pub fn end_scope(&self) {
|
||||
unsafe { msg_send![self, endScope] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcapturemanager>
|
||||
pub enum MTLCaptureManager {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLCaptureManager;
|
||||
pub struct CaptureManager;
|
||||
}
|
||||
|
||||
impl CaptureManager {
|
||||
pub fn shared<'a>() -> &'a CaptureManagerRef {
|
||||
unsafe {
|
||||
let class = class!(MTLCaptureManager);
|
||||
msg_send![class, sharedCaptureManager]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CaptureManagerRef {
|
||||
pub fn new_capture_scope_with_device(&self, device: &DeviceRef) -> CaptureScope {
|
||||
unsafe { msg_send![self, newCaptureScopeWithDevice: device] }
|
||||
}
|
||||
|
||||
pub fn new_capture_scope_with_command_queue(
|
||||
&self,
|
||||
command_queue: &CommandQueueRef,
|
||||
) -> CaptureScope {
|
||||
unsafe { msg_send![self, newCaptureScopeWithCommandQueue: command_queue] }
|
||||
}
|
||||
|
||||
pub fn default_capture_scope(&self) -> Option<&CaptureScopeRef> {
|
||||
unsafe { msg_send![self, defaultCaptureScope] }
|
||||
}
|
||||
|
||||
pub fn set_default_capture_scope(&self, scope: &CaptureScopeRef) {
|
||||
unsafe { msg_send![self, setDefaultCaptureScope: scope] }
|
||||
}
|
||||
|
||||
/// Starts capturing with the capture session defined by a descriptor object.
|
||||
///
|
||||
/// This function will panic if Metal capture is not enabled. Capture can be enabled by
|
||||
/// either:
|
||||
/// 1. Running from Xcode
|
||||
/// 2. Setting the environment variable `METAL_CAPTURE_ENABLED=1`
|
||||
/// 3. Adding an info.plist file containing the `MetalCaptureEnabled` key set to `YES`
|
||||
pub fn start_capture(&self, descriptor: &CaptureDescriptorRef) -> Result<(), String> {
|
||||
unsafe {
|
||||
Ok(try_objc! { err =>
|
||||
msg_send![self, startCaptureWithDescriptor: descriptor
|
||||
error: &mut err]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_capture_with_device(&self, device: &DeviceRef) {
|
||||
unsafe { msg_send![self, startCaptureWithDevice: device] }
|
||||
}
|
||||
|
||||
pub fn start_capture_with_command_queue(&self, command_queue: &CommandQueueRef) {
|
||||
unsafe { msg_send![self, startCaptureWithCommandQueue: command_queue] }
|
||||
}
|
||||
|
||||
pub fn start_capture_with_scope(&self, scope: &CaptureScopeRef) {
|
||||
unsafe { msg_send![self, startCaptureWithScope: scope] }
|
||||
}
|
||||
|
||||
pub fn stop_capture(&self) {
|
||||
unsafe { msg_send![self, stopCapture] }
|
||||
}
|
||||
|
||||
pub fn is_capturing(&self) -> bool {
|
||||
unsafe { msg_send![self, isCapturing] }
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcapturemanager/3237260-supportsdestination?language=objc>
|
||||
pub fn supports_destination(&self, destination: MTLCaptureDestination) -> bool {
|
||||
unsafe { msg_send![self, supportsDestination: destination] }
|
||||
}
|
||||
}
|
||||
178
third-party/vendor/metal/src/commandbuffer.rs
vendored
Normal file
178
third-party/vendor/metal/src/commandbuffer.rs
vendored
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
|
||||
use block::Block;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcommandbufferstatus>
|
||||
#[repr(u32)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLCommandBufferStatus {
|
||||
NotEnqueued = 0,
|
||||
Enqueued = 1,
|
||||
Committed = 2,
|
||||
Scheduled = 3,
|
||||
Completed = 4,
|
||||
Error = 5,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcommandbuffererror>
|
||||
#[repr(u32)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLCommandBufferError {
|
||||
None = 0,
|
||||
Internal = 1,
|
||||
Timeout = 2,
|
||||
PageFault = 3,
|
||||
Blacklisted = 4,
|
||||
NotPermitted = 7,
|
||||
OutOfMemory = 8,
|
||||
InvalidResource = 9,
|
||||
Memoryless = 10,
|
||||
DeviceRemoved = 11,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtldispatchtype>
|
||||
#[repr(u32)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLDispatchType {
|
||||
Serial = 0,
|
||||
Concurrent = 1,
|
||||
}
|
||||
|
||||
type CommandBufferHandler<'a> = Block<(&'a CommandBufferRef,), ()>;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcommandbuffer>.
|
||||
pub enum MTLCommandBuffer {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLCommandBuffer;
|
||||
pub struct CommandBuffer;
|
||||
}
|
||||
|
||||
impl CommandBufferRef {
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enqueue(&self) {
|
||||
unsafe { msg_send![self, enqueue] }
|
||||
}
|
||||
|
||||
pub fn commit(&self) {
|
||||
unsafe { msg_send![self, commit] }
|
||||
}
|
||||
|
||||
pub fn status(&self) -> MTLCommandBufferStatus {
|
||||
unsafe { msg_send![self, status] }
|
||||
}
|
||||
|
||||
pub fn present_drawable(&self, drawable: &DrawableRef) {
|
||||
unsafe { msg_send![self, presentDrawable: drawable] }
|
||||
}
|
||||
|
||||
pub fn wait_until_completed(&self) {
|
||||
unsafe { msg_send![self, waitUntilCompleted] }
|
||||
}
|
||||
|
||||
pub fn wait_until_scheduled(&self) {
|
||||
unsafe { msg_send![self, waitUntilScheduled] }
|
||||
}
|
||||
|
||||
pub fn add_completed_handler(&self, block: &CommandBufferHandler) {
|
||||
unsafe { msg_send![self, addCompletedHandler: block] }
|
||||
}
|
||||
|
||||
pub fn add_scheduled_handler(&self, block: &CommandBufferHandler) {
|
||||
unsafe { msg_send![self, addScheduledHandler: block] }
|
||||
}
|
||||
|
||||
pub fn new_blit_command_encoder(&self) -> &BlitCommandEncoderRef {
|
||||
unsafe { msg_send![self, blitCommandEncoder] }
|
||||
}
|
||||
|
||||
pub fn new_compute_command_encoder(&self) -> &ComputeCommandEncoderRef {
|
||||
unsafe { msg_send![self, computeCommandEncoder] }
|
||||
}
|
||||
|
||||
pub fn new_render_command_encoder(
|
||||
&self,
|
||||
descriptor: &RenderPassDescriptorRef,
|
||||
) -> &RenderCommandEncoderRef {
|
||||
unsafe { msg_send![self, renderCommandEncoderWithDescriptor: descriptor] }
|
||||
}
|
||||
|
||||
pub fn new_parallel_render_command_encoder(
|
||||
&self,
|
||||
descriptor: &RenderPassDescriptorRef,
|
||||
) -> &ParallelRenderCommandEncoderRef {
|
||||
unsafe { msg_send![self, parallelRenderCommandEncoderWithDescriptor: descriptor] }
|
||||
}
|
||||
|
||||
pub fn new_acceleration_structure_command_encoder(
|
||||
&self,
|
||||
) -> &AccelerationStructureCommandEncoderRef {
|
||||
unsafe { msg_send![self, accelerationStructureCommandEncoder] }
|
||||
}
|
||||
|
||||
pub fn compute_command_encoder_with_dispatch_type(
|
||||
&self,
|
||||
ty: MTLDispatchType,
|
||||
) -> &ComputeCommandEncoderRef {
|
||||
unsafe { msg_send![self, computeCommandEncoderWithDispatchType: ty] }
|
||||
}
|
||||
|
||||
pub fn compute_command_encoder_with_descriptor(
|
||||
&self,
|
||||
descriptor: &ComputePassDescriptorRef,
|
||||
) -> &ComputeCommandEncoderRef {
|
||||
unsafe { msg_send![self, computeCommandEncoderWithDescriptor: descriptor] }
|
||||
}
|
||||
|
||||
pub fn encode_signal_event(&self, event: &EventRef, new_value: u64) {
|
||||
unsafe {
|
||||
msg_send![self,
|
||||
encodeSignalEvent: event
|
||||
value: new_value
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encode_wait_for_event(&self, event: &EventRef, value: u64) {
|
||||
unsafe {
|
||||
msg_send![self,
|
||||
encodeWaitForEvent: event
|
||||
value: value
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_debug_group(&self, name: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(name);
|
||||
msg_send![self, pushDebugGroup: nslabel]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop_debug_group(&self) {
|
||||
unsafe { msg_send![self, popDebugGroup] }
|
||||
}
|
||||
}
|
||||
44
third-party/vendor/metal/src/commandqueue.rs
vendored
Normal file
44
third-party/vendor/metal/src/commandqueue.rs
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcommandqueue>.
|
||||
pub enum MTLCommandQueue {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLCommandQueue;
|
||||
pub struct CommandQueue;
|
||||
}
|
||||
|
||||
impl CommandQueueRef {
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_command_buffer(&self) -> &CommandBufferRef {
|
||||
unsafe { msg_send![self, commandBuffer] }
|
||||
}
|
||||
|
||||
pub fn new_command_buffer_with_unretained_references(&self) -> &CommandBufferRef {
|
||||
unsafe { msg_send![self, commandBufferWithUnretainedReferences] }
|
||||
}
|
||||
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
}
|
||||
103
third-party/vendor/metal/src/computepass.rs
vendored
Normal file
103
third-party/vendor/metal/src/computepass.rs
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
use super::*;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcomputepassdescriptor>
|
||||
pub enum MTLComputePassDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLComputePassDescriptor;
|
||||
pub struct ComputePassDescriptor;
|
||||
}
|
||||
|
||||
impl ComputePassDescriptor {
|
||||
/// Creates a default compute pass descriptor with no attachments.
|
||||
pub fn new<'a>() -> &'a ComputePassDescriptorRef {
|
||||
unsafe { msg_send![class!(MTLComputePassDescriptor), computePassDescriptor] }
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputePassDescriptorRef {
|
||||
pub fn sample_buffer_attachments(
|
||||
&self,
|
||||
) -> &ComputePassSampleBufferAttachmentDescriptorArrayRef {
|
||||
unsafe { msg_send![self, sampleBufferAttachments] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcomputepasssamplebufferattachmentdescriptorarray>
|
||||
pub enum MTLComputePassSampleBufferAttachmentDescriptorArray {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLComputePassSampleBufferAttachmentDescriptorArray;
|
||||
pub struct ComputePassSampleBufferAttachmentDescriptorArray;
|
||||
}
|
||||
|
||||
impl ComputePassSampleBufferAttachmentDescriptorArrayRef {
|
||||
pub fn object_at(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
) -> Option<&ComputePassSampleBufferAttachmentDescriptorRef> {
|
||||
unsafe { msg_send![self, objectAtIndexedSubscript: index] }
|
||||
}
|
||||
|
||||
pub fn set_object_at(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
attachment: Option<&ComputePassSampleBufferAttachmentDescriptorRef>,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self, setObject:attachment
|
||||
atIndexedSubscript:index]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcomputepasssamplebufferattachmentdescriptor>
|
||||
pub enum MTLComputePassSampleBufferAttachmentDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLComputePassSampleBufferAttachmentDescriptor;
|
||||
pub struct ComputePassSampleBufferAttachmentDescriptor;
|
||||
}
|
||||
|
||||
impl ComputePassSampleBufferAttachmentDescriptor {
|
||||
pub fn new() -> Self {
|
||||
let class = class!(MTLComputePassSampleBufferAttachmentDescriptor);
|
||||
unsafe { msg_send![class, new] }
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputePassSampleBufferAttachmentDescriptorRef {
|
||||
pub fn sample_buffer(&self) -> &CounterSampleBufferRef {
|
||||
unsafe { msg_send![self, sampleBuffer] }
|
||||
}
|
||||
|
||||
pub fn set_sample_buffer(&self, sample_buffer: &CounterSampleBufferRef) {
|
||||
unsafe { msg_send![self, setSampleBuffer: sample_buffer] }
|
||||
}
|
||||
|
||||
pub fn start_of_encoder_sample_index(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, startOfEncoderSampleIndex] }
|
||||
}
|
||||
|
||||
pub fn set_start_of_encoder_sample_index(&self, start_of_encoder_sample_index: NSUInteger) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
setStartOfEncoderSampleIndex: start_of_encoder_sample_index
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end_of_encoder_sample_index(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, endOfEncoderSampleIndex] }
|
||||
}
|
||||
|
||||
pub fn set_end_of_encoder_sample_index(&self, end_of_encoder_sample_index: NSUInteger) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
setEndOfEncoderSampleIndex: end_of_encoder_sample_index
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
152
third-party/vendor/metal/src/constants.rs
vendored
Normal file
152
third-party/vendor/metal/src/constants.rs
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlpixelformat>
|
||||
#[repr(u64)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub enum MTLPixelFormat {
|
||||
Invalid = 0,
|
||||
A8Unorm = 1,
|
||||
R8Unorm = 10,
|
||||
R8Unorm_sRGB = 11,
|
||||
R8Snorm = 12,
|
||||
R8Uint = 13,
|
||||
R8Sint = 14,
|
||||
R16Unorm = 20,
|
||||
R16Snorm = 22,
|
||||
R16Uint = 23,
|
||||
R16Sint = 24,
|
||||
R16Float = 25,
|
||||
RG8Unorm = 30,
|
||||
RG8Unorm_sRGB = 31,
|
||||
RG8Snorm = 32,
|
||||
RG8Uint = 33,
|
||||
RG8Sint = 34,
|
||||
B5G6R5Unorm = 40,
|
||||
A1BGR5Unorm = 41,
|
||||
ABGR4Unorm = 42,
|
||||
BGR5A1Unorm = 43,
|
||||
R32Uint = 53,
|
||||
R32Sint = 54,
|
||||
R32Float = 55,
|
||||
RG16Unorm = 60,
|
||||
RG16Snorm = 62,
|
||||
RG16Uint = 63,
|
||||
RG16Sint = 64,
|
||||
RG16Float = 65,
|
||||
RGBA8Unorm = 70,
|
||||
RGBA8Unorm_sRGB = 71,
|
||||
RGBA8Snorm = 72,
|
||||
RGBA8Uint = 73,
|
||||
RGBA8Sint = 74,
|
||||
BGRA8Unorm = 80,
|
||||
BGRA8Unorm_sRGB = 81,
|
||||
RGB10A2Unorm = 90,
|
||||
RGB10A2Uint = 91,
|
||||
RG11B10Float = 92,
|
||||
RGB9E5Float = 93,
|
||||
BGR10A2Unorm = 94,
|
||||
RG32Uint = 103,
|
||||
RG32Sint = 104,
|
||||
RG32Float = 105,
|
||||
RGBA16Unorm = 110,
|
||||
RGBA16Snorm = 112,
|
||||
RGBA16Uint = 113,
|
||||
RGBA16Sint = 114,
|
||||
RGBA16Float = 115,
|
||||
RGBA32Uint = 123,
|
||||
RGBA32Sint = 124,
|
||||
RGBA32Float = 125,
|
||||
BC1_RGBA = 130,
|
||||
BC1_RGBA_sRGB = 131,
|
||||
BC2_RGBA = 132,
|
||||
BC2_RGBA_sRGB = 133,
|
||||
BC3_RGBA = 134,
|
||||
BC3_RGBA_sRGB = 135,
|
||||
BC4_RUnorm = 140,
|
||||
BC4_RSnorm = 141,
|
||||
BC5_RGUnorm = 142,
|
||||
BC5_RGSnorm = 143,
|
||||
BC6H_RGBFloat = 150,
|
||||
BC6H_RGBUfloat = 151,
|
||||
BC7_RGBAUnorm = 152,
|
||||
BC7_RGBAUnorm_sRGB = 153,
|
||||
PVRTC_RGB_2BPP = 160,
|
||||
PVRTC_RGB_2BPP_sRGB = 161,
|
||||
PVRTC_RGB_4BPP = 162,
|
||||
PVRTC_RGB_4BPP_sRGB = 163,
|
||||
PVRTC_RGBA_2BPP = 164,
|
||||
PVRTC_RGBA_2BPP_sRGB = 165,
|
||||
PVRTC_RGBA_4BPP = 166,
|
||||
PVRTC_RGBA_4BPP_sRGB = 167,
|
||||
EAC_R11Unorm = 170,
|
||||
EAC_R11Snorm = 172,
|
||||
EAC_RG11Unorm = 174,
|
||||
EAC_RG11Snorm = 176,
|
||||
EAC_RGBA8 = 178,
|
||||
EAC_RGBA8_sRGB = 179,
|
||||
ETC2_RGB8 = 180,
|
||||
ETC2_RGB8_sRGB = 181,
|
||||
ETC2_RGB8A1 = 182,
|
||||
ETC2_RGB8A1_sRGB = 183,
|
||||
ASTC_4x4_sRGB = 186,
|
||||
ASTC_5x4_sRGB = 187,
|
||||
ASTC_5x5_sRGB = 188,
|
||||
ASTC_6x5_sRGB = 189,
|
||||
ASTC_6x6_sRGB = 190,
|
||||
ASTC_8x5_sRGB = 192,
|
||||
ASTC_8x6_sRGB = 193,
|
||||
ASTC_8x8_sRGB = 194,
|
||||
ASTC_10x5_sRGB = 195,
|
||||
ASTC_10x6_sRGB = 196,
|
||||
ASTC_10x8_sRGB = 197,
|
||||
ASTC_10x10_sRGB = 198,
|
||||
ASTC_12x10_sRGB = 199,
|
||||
ASTC_12x12_sRGB = 200,
|
||||
ASTC_4x4_LDR = 204,
|
||||
ASTC_5x4_LDR = 205,
|
||||
ASTC_5x5_LDR = 206,
|
||||
ASTC_6x5_LDR = 207,
|
||||
ASTC_6x6_LDR = 208,
|
||||
ASTC_8x5_LDR = 210,
|
||||
ASTC_8x6_LDR = 211,
|
||||
ASTC_8x8_LDR = 212,
|
||||
ASTC_10x5_LDR = 213,
|
||||
ASTC_10x6_LDR = 214,
|
||||
ASTC_10x8_LDR = 215,
|
||||
ASTC_10x10_LDR = 216,
|
||||
ASTC_12x10_LDR = 217,
|
||||
ASTC_12x12_LDR = 218,
|
||||
ASTC_4x4_HDR = 222,
|
||||
ASTC_5x4_HDR = 223,
|
||||
ASTC_5x5_HDR = 224,
|
||||
ASTC_6x5_HDR = 225,
|
||||
ASTC_6x6_HDR = 226,
|
||||
ASTC_8x5_HDR = 228,
|
||||
ASTC_8x6_HDR = 229,
|
||||
ASTC_8x8_HDR = 230,
|
||||
ASTC_10x5_HDR = 231,
|
||||
ASTC_10x6_HDR = 232,
|
||||
ASTC_10x8_HDR = 233,
|
||||
ASTC_10x10_HDR = 234,
|
||||
ASTC_12x10_HDR = 235,
|
||||
ASTC_12x12_HDR = 236,
|
||||
GBGR422 = 240,
|
||||
BGRG422 = 241,
|
||||
Depth16Unorm = 250,
|
||||
Depth32Float = 252,
|
||||
Stencil8 = 253,
|
||||
Depth24Unorm_Stencil8 = 255,
|
||||
Depth32Float_Stencil8 = 260,
|
||||
X32_Stencil8 = 261,
|
||||
X24_Stencil8 = 262,
|
||||
BGRA10_XR = 552,
|
||||
BGRA10_XR_SRGB = 553,
|
||||
BGR10_XR = 554,
|
||||
BGR10_XR_SRGB = 555,
|
||||
}
|
||||
102
third-party/vendor/metal/src/counters.rs
vendored
Normal file
102
third-party/vendor/metal/src/counters.rs
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
use crate::MTLStorageMode;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcountersamplebufferdescriptor>
|
||||
pub enum MTLCounterSampleBufferDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLCounterSampleBufferDescriptor;
|
||||
pub struct CounterSampleBufferDescriptor;
|
||||
}
|
||||
|
||||
impl CounterSampleBufferDescriptor {
|
||||
pub fn new() -> Self {
|
||||
let class = class!(MTLCounterSampleBufferDescriptor);
|
||||
unsafe { msg_send![class, new] }
|
||||
}
|
||||
}
|
||||
|
||||
impl CounterSampleBufferDescriptorRef {
|
||||
pub fn counter_set(&self) -> &CounterSetRef {
|
||||
unsafe { msg_send![self, counterSet] }
|
||||
}
|
||||
|
||||
pub fn set_counter_set(&self, counter_set: &CounterSetRef) {
|
||||
unsafe { msg_send![self, setCounterSet: counter_set] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sample_count(&self) -> u64 {
|
||||
unsafe { msg_send![self, sampleCount] }
|
||||
}
|
||||
|
||||
pub fn set_sample_count(&self, sample_count: u64) {
|
||||
unsafe { msg_send![self, setSampleCount: sample_count] }
|
||||
}
|
||||
|
||||
pub fn storage_mode(&self) -> MTLStorageMode {
|
||||
unsafe { msg_send![self, storageMode] }
|
||||
}
|
||||
|
||||
pub fn set_storage_mode(&self, storage_mode: MTLStorageMode) {
|
||||
unsafe { msg_send![self, setStorageMode: storage_mode] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcountersamplebuffer>
|
||||
pub enum MTLCounterSampleBuffer {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLCounterSampleBuffer;
|
||||
pub struct CounterSampleBuffer;
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcounter>
|
||||
pub enum MTLCounter {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLCounter;
|
||||
pub struct Counter;
|
||||
}
|
||||
|
||||
impl CounterRef {}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcounterset>
|
||||
pub enum MTLCounterSet {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLCounterSet;
|
||||
pub struct CounterSet;
|
||||
}
|
||||
|
||||
impl CounterSetRef {
|
||||
pub fn name(&self) -> &str {
|
||||
unsafe {
|
||||
let name = msg_send![self, name];
|
||||
crate::nsstring_as_str(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcommoncounterset>
|
||||
pub enum MTLCommonCounterSet {}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcommoncounter>
|
||||
pub enum MTLCommonCounter {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLCommonCounter;
|
||||
pub struct CommonCounter;
|
||||
}
|
||||
190
third-party/vendor/metal/src/depthstencil.rs
vendored
Normal file
190
third-party/vendor/metal/src/depthstencil.rs
vendored
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use crate::DeviceRef;
|
||||
use objc::runtime::{NO, YES};
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcomparefunction>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLCompareFunction {
|
||||
Never = 0,
|
||||
Less = 1,
|
||||
Equal = 2,
|
||||
LessEqual = 3,
|
||||
Greater = 4,
|
||||
NotEqual = 5,
|
||||
GreaterEqual = 6,
|
||||
Always = 7,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlstenciloperation>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLStencilOperation {
|
||||
Keep = 0,
|
||||
Zero = 1,
|
||||
Replace = 2,
|
||||
IncrementClamp = 3,
|
||||
DecrementClamp = 4,
|
||||
Invert = 5,
|
||||
IncrementWrap = 6,
|
||||
DecrementWrap = 7,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlstencildescriptor>
|
||||
pub enum MTLStencilDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLStencilDescriptor;
|
||||
pub struct StencilDescriptor;
|
||||
}
|
||||
|
||||
impl StencilDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLStencilDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StencilDescriptorRef {
|
||||
pub fn stencil_compare_function(&self) -> MTLCompareFunction {
|
||||
unsafe { msg_send![self, stencilCompareFunction] }
|
||||
}
|
||||
|
||||
pub fn set_stencil_compare_function(&self, func: MTLCompareFunction) {
|
||||
unsafe { msg_send![self, setStencilCompareFunction: func] }
|
||||
}
|
||||
|
||||
pub fn stencil_failure_operation(&self) -> MTLStencilOperation {
|
||||
unsafe { msg_send![self, stencilFailureOperation] }
|
||||
}
|
||||
|
||||
pub fn set_stencil_failure_operation(&self, operation: MTLStencilOperation) {
|
||||
unsafe { msg_send![self, setStencilFailureOperation: operation] }
|
||||
}
|
||||
|
||||
pub fn depth_failure_operation(&self) -> MTLStencilOperation {
|
||||
unsafe { msg_send![self, depthFailureOperation] }
|
||||
}
|
||||
|
||||
pub fn set_depth_failure_operation(&self, operation: MTLStencilOperation) {
|
||||
unsafe { msg_send![self, setDepthFailureOperation: operation] }
|
||||
}
|
||||
|
||||
pub fn depth_stencil_pass_operation(&self) -> MTLStencilOperation {
|
||||
unsafe { msg_send![self, depthStencilPassOperation] }
|
||||
}
|
||||
|
||||
pub fn set_depth_stencil_pass_operation(&self, operation: MTLStencilOperation) {
|
||||
unsafe { msg_send![self, setDepthStencilPassOperation: operation] }
|
||||
}
|
||||
|
||||
pub fn read_mask(&self) -> u32 {
|
||||
unsafe { msg_send![self, readMask] }
|
||||
}
|
||||
|
||||
pub fn set_read_mask(&self, mask: u32) {
|
||||
unsafe { msg_send![self, setReadMask: mask] }
|
||||
}
|
||||
|
||||
pub fn write_mask(&self) -> u32 {
|
||||
unsafe { msg_send![self, writeMask] }
|
||||
}
|
||||
|
||||
pub fn set_write_mask(&self, mask: u32) {
|
||||
unsafe { msg_send![self, setWriteMask: mask] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtldepthstencildescriptor>
|
||||
pub enum MTLDepthStencilDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLDepthStencilDescriptor;
|
||||
pub struct DepthStencilDescriptor;
|
||||
}
|
||||
|
||||
impl DepthStencilDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLDepthStencilDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DepthStencilDescriptorRef {
|
||||
pub fn depth_compare_function(&self) -> MTLCompareFunction {
|
||||
unsafe { msg_send![self, depthCompareFunction] }
|
||||
}
|
||||
|
||||
pub fn set_depth_compare_function(&self, func: MTLCompareFunction) {
|
||||
unsafe { msg_send![self, setDepthCompareFunction: func] }
|
||||
}
|
||||
|
||||
pub fn depth_write_enabled(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isDepthWriteEnabled] }
|
||||
}
|
||||
|
||||
pub fn set_depth_write_enabled(&self, enabled: bool) {
|
||||
unsafe { msg_send![self, setDepthWriteEnabled: enabled] }
|
||||
}
|
||||
|
||||
pub fn front_face_stencil(&self) -> Option<&StencilDescriptorRef> {
|
||||
unsafe { msg_send![self, frontFaceStencil] }
|
||||
}
|
||||
|
||||
pub fn set_front_face_stencil(&self, descriptor: Option<&StencilDescriptorRef>) {
|
||||
unsafe { msg_send![self, setFrontFaceStencil: descriptor] }
|
||||
}
|
||||
|
||||
pub fn back_face_stencil(&self) -> Option<&StencilDescriptorRef> {
|
||||
unsafe { msg_send![self, backFaceStencil] }
|
||||
}
|
||||
|
||||
pub fn set_back_face_stencil(&self, descriptor: Option<&StencilDescriptorRef>) {
|
||||
unsafe { msg_send![self, setBackFaceStencil: descriptor] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtldepthstencilstate>
|
||||
pub enum MTLDepthStencilState {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLDepthStencilState;
|
||||
pub struct DepthStencilState;
|
||||
}
|
||||
|
||||
impl DepthStencilStateRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
}
|
||||
2106
third-party/vendor/metal/src/device.rs
vendored
Normal file
2106
third-party/vendor/metal/src/device.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
26
third-party/vendor/metal/src/drawable.rs
vendored
Normal file
26
third-party/vendor/metal/src/drawable.rs
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::NSUInteger;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtldrawable>
|
||||
pub enum MTLDrawable {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLDrawable;
|
||||
pub struct Drawable;
|
||||
}
|
||||
|
||||
impl DrawableRef {
|
||||
pub fn present(&self) {
|
||||
unsafe { msg_send![self, present] }
|
||||
}
|
||||
|
||||
pub fn drawable_id(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, drawableID] }
|
||||
}
|
||||
}
|
||||
1870
third-party/vendor/metal/src/encoder.rs
vendored
Normal file
1870
third-party/vendor/metal/src/encoder.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
209
third-party/vendor/metal/src/heap.rs
vendored
Normal file
209
third-party/vendor/metal/src/heap.rs
vendored
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Only available on macos(10.15), ios(13.0)
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlheaptype/>
|
||||
#[repr(u64)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum MTLHeapType {
|
||||
Automatic = 0,
|
||||
Placement = 1,
|
||||
/// Only available on macos(11.0), macCatalyst(14.0)
|
||||
Sparse = 2,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlheap/>
|
||||
pub enum MTLHeap {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLHeap;
|
||||
pub struct Heap;
|
||||
}
|
||||
|
||||
impl HeapRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cpu_cache_mode(&self) -> MTLCPUCacheMode {
|
||||
unsafe { msg_send![self, cpuCacheMode] }
|
||||
}
|
||||
|
||||
pub fn storage_mode(&self) -> MTLStorageMode {
|
||||
unsafe { msg_send![self, storageMode] }
|
||||
}
|
||||
|
||||
/// Only available on macos(10.15), ios(13.0)
|
||||
pub fn hazard_tracking_mode(&self) -> MTLHazardTrackingMode {
|
||||
unsafe { msg_send![self, hazardTrackingMode] }
|
||||
}
|
||||
|
||||
/// Only available on macos(10.15), ios(13.0)
|
||||
pub fn resource_options(&self) -> MTLResourceOptions {
|
||||
unsafe { msg_send![self, resourceOptions] }
|
||||
}
|
||||
|
||||
pub fn set_purgeable_state(&self, state: MTLPurgeableState) -> MTLPurgeableState {
|
||||
unsafe { msg_send![self, setPurgeableState: state] }
|
||||
}
|
||||
|
||||
pub fn size(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, size] }
|
||||
}
|
||||
|
||||
pub fn used_size(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, usedSize] }
|
||||
}
|
||||
|
||||
/// Only available on macos(10.15), ios(13.0)
|
||||
pub fn heap_type(&self) -> MTLHeapType {
|
||||
unsafe { msg_send![self, type] }
|
||||
}
|
||||
|
||||
/// Only available on macos(10.13), ios(11.0)
|
||||
pub fn current_allocated_size(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, currentAllocatedSize] }
|
||||
}
|
||||
|
||||
pub fn max_available_size_with_alignment(&self, alignment: NSUInteger) -> NSUInteger {
|
||||
unsafe { msg_send![self, maxAvailableSizeWithAlignment: alignment] }
|
||||
}
|
||||
|
||||
pub fn new_buffer(&self, length: u64, options: MTLResourceOptions) -> Option<Buffer> {
|
||||
unsafe {
|
||||
let ptr: *mut MTLBuffer = msg_send![self, newBufferWithLength:length
|
||||
options:options];
|
||||
if !ptr.is_null() {
|
||||
Some(Buffer::from_ptr(ptr))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_texture(&self, descriptor: &TextureDescriptorRef) -> Option<Texture> {
|
||||
unsafe {
|
||||
let ptr: *mut MTLTexture = msg_send![self, newTextureWithDescriptor: descriptor];
|
||||
if !ptr.is_null() {
|
||||
Some(Texture::from_ptr(ptr))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on macOS 10.15+ & iOS 13.0+
|
||||
pub fn new_buffer_with_offset(
|
||||
&self,
|
||||
length: u64,
|
||||
options: MTLResourceOptions,
|
||||
offset: u64,
|
||||
) -> Option<Buffer> {
|
||||
unsafe {
|
||||
let ptr: *mut MTLBuffer = msg_send![self, newBufferWithLength:length
|
||||
options:options
|
||||
offset:offset];
|
||||
if !ptr.is_null() {
|
||||
Some(Buffer::from_ptr(ptr))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on macOS 10.15+ & iOS 13.0+
|
||||
pub fn new_texture_with_offset(
|
||||
&self,
|
||||
descriptor: &TextureDescriptorRef,
|
||||
offset: u64,
|
||||
) -> Option<Texture> {
|
||||
unsafe {
|
||||
let ptr: *mut MTLTexture = msg_send![self, newTextureWithDescriptor:descriptor
|
||||
offset:offset];
|
||||
if !ptr.is_null() {
|
||||
Some(Texture::from_ptr(ptr))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlheapdescriptor/>
|
||||
pub enum MTLHeapDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLHeapDescriptor;
|
||||
pub struct HeapDescriptor;
|
||||
}
|
||||
|
||||
impl HeapDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLHeapDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HeapDescriptorRef {
|
||||
pub fn cpu_cache_mode(&self) -> MTLCPUCacheMode {
|
||||
unsafe { msg_send![self, cpuCacheMode] }
|
||||
}
|
||||
|
||||
pub fn set_cpu_cache_mode(&self, mode: MTLCPUCacheMode) {
|
||||
unsafe { msg_send![self, setCpuCacheMode: mode] }
|
||||
}
|
||||
|
||||
pub fn storage_mode(&self) -> MTLStorageMode {
|
||||
unsafe { msg_send![self, storageMode] }
|
||||
}
|
||||
|
||||
pub fn set_storage_mode(&self, mode: MTLStorageMode) {
|
||||
unsafe { msg_send![self, setStorageMode: mode] }
|
||||
}
|
||||
|
||||
pub fn size(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, size] }
|
||||
}
|
||||
|
||||
pub fn set_size(&self, size: NSUInteger) {
|
||||
unsafe { msg_send![self, setSize: size] }
|
||||
}
|
||||
|
||||
/// Only available on macos(10.15), ios(13.0)
|
||||
pub fn hazard_tracking_mode(&self) -> MTLHazardTrackingMode {
|
||||
unsafe { msg_send![self, hazardTrackingMode] }
|
||||
}
|
||||
|
||||
/// Only available on macos(10.15), ios(13.0)
|
||||
pub fn resource_options(&self) -> MTLResourceOptions {
|
||||
unsafe { msg_send![self, resourceOptions] }
|
||||
}
|
||||
|
||||
/// Only available on macos(10.15), ios(13.0)
|
||||
pub fn heap_type(&self) -> MTLHeapType {
|
||||
unsafe { msg_send![self, type] }
|
||||
}
|
||||
}
|
||||
337
third-party/vendor/metal/src/indirect_encoder.rs
vendored
Normal file
337
third-party/vendor/metal/src/indirect_encoder.rs
vendored
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
use super::*;
|
||||
|
||||
bitflags! {
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlindirectcommandtype/>
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct MTLIndirectCommandType: NSUInteger {
|
||||
const Draw = 1 << 0;
|
||||
const DrawIndexed = 1 << 1;
|
||||
const DrawPatches = 1 << 2;
|
||||
const DrawIndexedPatches = 1 << 3;
|
||||
const ConcurrentDispatch = 1 << 4;
|
||||
const ConcurrentDispatchThreads = 1 << 5;
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlindirectcommandbufferdescriptor/>
|
||||
pub enum MTLIndirectCommandBufferDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLIndirectCommandBufferDescriptor;
|
||||
pub struct IndirectCommandBufferDescriptor;
|
||||
}
|
||||
|
||||
impl IndirectCommandBufferDescriptorRef {
|
||||
pub fn command_types(&self) -> MTLIndirectCommandType {
|
||||
unsafe { msg_send![self, commandTypes] }
|
||||
}
|
||||
|
||||
pub fn set_command_types(&self, types: MTLIndirectCommandType) {
|
||||
unsafe { msg_send![self, setCommandTypes: types] }
|
||||
}
|
||||
|
||||
pub fn inherit_buffers(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, inheritBuffers] }
|
||||
}
|
||||
|
||||
pub fn set_inherit_buffers(&self, inherit: bool) {
|
||||
unsafe { msg_send![self, setInheritBuffers: inherit] }
|
||||
}
|
||||
|
||||
pub fn inherit_pipeline_state(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, inheritPipelineState] }
|
||||
}
|
||||
|
||||
pub fn set_inherit_pipeline_state(&self, inherit: bool) {
|
||||
unsafe { msg_send![self, setInheritPipelineState: inherit] }
|
||||
}
|
||||
|
||||
pub fn max_vertex_buffer_bind_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, maxVertexBufferBindCount] }
|
||||
}
|
||||
|
||||
pub fn set_max_vertex_buffer_bind_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setMaxVertexBufferBindCount: count] }
|
||||
}
|
||||
|
||||
pub fn max_fragment_buffer_bind_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, maxFragmentBufferBindCount] }
|
||||
}
|
||||
|
||||
pub fn set_max_fragment_buffer_bind_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setMaxFragmentBufferBindCount: count] }
|
||||
}
|
||||
|
||||
pub fn max_kernel_buffer_bind_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, maxKernelBufferBindCount] }
|
||||
}
|
||||
|
||||
pub fn set_max_kernel_buffer_bind_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setMaxKernelBufferBindCount: count] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlindirectcommandbuffer/>
|
||||
pub enum MTLIndirectCommandBuffer {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLIndirectCommandBuffer;
|
||||
pub struct IndirectCommandBuffer;
|
||||
type ParentType = Resource;
|
||||
}
|
||||
|
||||
impl IndirectCommandBufferRef {
|
||||
pub fn size(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, size] }
|
||||
}
|
||||
|
||||
pub fn indirect_render_command_at_index(&self, index: NSUInteger) -> &IndirectRenderCommandRef {
|
||||
unsafe { msg_send![self, indirectRenderCommandAtIndex: index] }
|
||||
}
|
||||
|
||||
pub fn indirect_compute_command_at_index(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
) -> &IndirectComputeCommandRef {
|
||||
unsafe { msg_send![self, indirectComputeCommandAtIndex: index] }
|
||||
}
|
||||
|
||||
pub fn reset_with_range(&self, range: crate::NSRange) {
|
||||
unsafe { msg_send![self, resetWithRange: range] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlindirectrendercommand/>
|
||||
pub enum MTLIndirectRenderCommand {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLIndirectRenderCommand;
|
||||
pub struct IndirectRenderCommand;
|
||||
}
|
||||
|
||||
impl IndirectRenderCommandRef {
|
||||
pub fn set_render_pipeline_state(&self, pipeline_state: &RenderPipelineStateRef) {
|
||||
unsafe { msg_send![self, setRenderPipelineState: pipeline_state] }
|
||||
}
|
||||
|
||||
pub fn set_vertex_buffer(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
buffer: Option<&BufferRef>,
|
||||
offset: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self,
|
||||
setVertexBuffer: buffer
|
||||
offset: offset
|
||||
atIndex: index
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_fragment_buffer(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
buffer: Option<&BufferRef>,
|
||||
offset: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self,
|
||||
setFragmentBuffer:buffer
|
||||
offset:offset
|
||||
atIndex:index
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_primitives(
|
||||
&self,
|
||||
primitive_type: MTLPrimitiveType,
|
||||
vertex_start: NSUInteger,
|
||||
vertex_count: NSUInteger,
|
||||
instance_count: NSUInteger,
|
||||
base_instance: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self,
|
||||
drawPrimitives: primitive_type
|
||||
vertexStart: vertex_start
|
||||
vertexCount: vertex_count
|
||||
instanceCount: instance_count
|
||||
baseInstance: base_instance
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_indexed_primitives(
|
||||
&self,
|
||||
primitive_type: MTLPrimitiveType,
|
||||
index_count: NSUInteger,
|
||||
index_type: MTLIndexType,
|
||||
index_buffer: &BufferRef,
|
||||
index_buffer_offset: NSUInteger,
|
||||
instance_count: NSUInteger,
|
||||
base_vertex: NSUInteger,
|
||||
base_instance: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self,
|
||||
drawIndexedPrimitives: primitive_type
|
||||
indexCount: index_count
|
||||
indexType: index_type
|
||||
indexBuffer: index_buffer
|
||||
indexBufferOffset: index_buffer_offset
|
||||
instanceCount: instance_count
|
||||
baseVertex: base_vertex
|
||||
baseInstance: base_instance
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_patches(
|
||||
&self,
|
||||
number_of_patch_control_points: NSUInteger,
|
||||
patch_start: NSUInteger,
|
||||
patch_count: NSUInteger,
|
||||
patch_index_buffer: &BufferRef,
|
||||
patch_index_buffer_offset: NSUInteger,
|
||||
instance_count: NSUInteger,
|
||||
base_instance: NSUInteger,
|
||||
tesselation_factor_buffer: &BufferRef,
|
||||
tesselation_factor_buffer_offset: NSUInteger,
|
||||
tesselation_factor_buffer_instance_stride: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self,
|
||||
drawPatches: number_of_patch_control_points
|
||||
patchStart: patch_start
|
||||
patchCount: patch_count
|
||||
patchIndexBuffer: patch_index_buffer
|
||||
patchIndexBufferOffset: patch_index_buffer_offset
|
||||
instanceCount: instance_count
|
||||
baseInstance: base_instance
|
||||
tessellationFactorBuffer: tesselation_factor_buffer
|
||||
tessellationFactorBufferOffset: tesselation_factor_buffer_offset
|
||||
tessellationFactorBufferInstanceStride: tesselation_factor_buffer_instance_stride
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_indexed_patches(
|
||||
&self,
|
||||
number_of_patch_control_points: NSUInteger,
|
||||
patch_start: NSUInteger,
|
||||
patch_count: NSUInteger,
|
||||
patch_index_buffer: &BufferRef,
|
||||
patch_index_buffer_offset: NSUInteger,
|
||||
control_point_index_buffer: &BufferRef,
|
||||
control_point_index_buffer_offset: NSUInteger,
|
||||
instance_count: NSUInteger,
|
||||
base_instance: NSUInteger,
|
||||
tesselation_factor_buffer: &BufferRef,
|
||||
tesselation_factor_buffer_offset: NSUInteger,
|
||||
tesselation_factor_buffer_instance_stride: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self,
|
||||
drawIndexedPatches: number_of_patch_control_points
|
||||
patchStart: patch_start
|
||||
patchCount: patch_count
|
||||
patchIndexBuffer: patch_index_buffer
|
||||
patchIndexBufferOffset: patch_index_buffer_offset
|
||||
controlPointIndexBuffer: control_point_index_buffer
|
||||
controlPointIndexBufferOffset: control_point_index_buffer_offset
|
||||
instanceCount: instance_count
|
||||
baseInstance: base_instance
|
||||
tessellationFactorBuffer: tesselation_factor_buffer
|
||||
tessellationFactorBufferOffset: tesselation_factor_buffer_offset
|
||||
tessellationFactorBufferInstanceStride: tesselation_factor_buffer_instance_stride
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&self) {
|
||||
unsafe { msg_send![self, reset] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlindirectcomputecommand/>
|
||||
pub enum MTLIndirectComputeCommand {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLIndirectComputeCommand;
|
||||
pub struct IndirectComputeCommand;
|
||||
}
|
||||
|
||||
impl IndirectComputeCommandRef {
|
||||
pub fn set_compute_pipeline_state(&self, state: &ComputePipelineStateRef) {
|
||||
unsafe { msg_send![self, setComputePipelineState: state] }
|
||||
}
|
||||
|
||||
pub fn set_kernel_buffer(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
buffer: Option<&BufferRef>,
|
||||
offset: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self,
|
||||
setKernelBuffer: buffer
|
||||
offset: offset
|
||||
atIndex: index
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_threadgroup_memory_length(&self, index: NSUInteger, length: NSUInteger) {
|
||||
unsafe {
|
||||
msg_send![self,
|
||||
setThreadgroupMemoryLength: length
|
||||
atIndex: index
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_stage_in_region(&self, region: MTLRegion) {
|
||||
unsafe { msg_send![self, setStageInRegion: region] }
|
||||
}
|
||||
|
||||
pub fn set_barrier(&self) {
|
||||
unsafe { msg_send![self, setBarrier] }
|
||||
}
|
||||
|
||||
pub fn clear_barrier(&self) {
|
||||
unsafe { msg_send![self, clearBarrier] }
|
||||
}
|
||||
|
||||
pub fn concurrent_dispatch_threadgroups(
|
||||
&self,
|
||||
thread_groups_per_grid: MTLSize,
|
||||
threads_per_threadgroup: MTLSize,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self,
|
||||
concurrentDispatchThreadgroups: thread_groups_per_grid
|
||||
threadsPerThreadgroup: threads_per_threadgroup
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn concurrent_dispatch_threads(
|
||||
&self,
|
||||
thread_groups_per_grid: MTLSize,
|
||||
threads_per_threadgroup: MTLSize,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self,
|
||||
concurrentDispatchThreads: thread_groups_per_grid
|
||||
threadsPerThreadgroup: threads_per_threadgroup
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&self) {
|
||||
unsafe { msg_send![self, reset] }
|
||||
}
|
||||
}
|
||||
652
third-party/vendor/metal/src/lib.rs
vendored
Normal file
652
third-party/vendor/metal/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,652 @@
|
|||
// Copyright 2023 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
#![allow(deprecated)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
#[macro_use]
|
||||
pub extern crate bitflags;
|
||||
#[macro_use]
|
||||
pub extern crate log;
|
||||
#[macro_use]
|
||||
pub extern crate objc;
|
||||
#[macro_use]
|
||||
pub extern crate foreign_types;
|
||||
#[macro_use]
|
||||
pub extern crate paste;
|
||||
|
||||
use std::{
|
||||
borrow::{Borrow, ToOwned},
|
||||
marker::PhantomData,
|
||||
mem,
|
||||
ops::Deref,
|
||||
os::raw::c_void,
|
||||
};
|
||||
|
||||
use core_graphics_types::{base::CGFloat, geometry::CGSize};
|
||||
use foreign_types::ForeignType;
|
||||
use objc::runtime::{Object, NO, YES};
|
||||
|
||||
/// See <https://developer.apple.com/documentation/objectivec/nsinteger>
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub type NSInteger = i64;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/objectivec/nsinteger>
|
||||
#[cfg(not(target_pointer_width = "64"))]
|
||||
pub type NSInteger = i32;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/objectivec/nsuinteger>
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub type NSUInteger = u64;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/objectivec/nsuinteger>
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub type NSUInteger = u32;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/foundation/nsrange>
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct NSRange {
|
||||
pub location: NSUInteger,
|
||||
pub length: NSUInteger,
|
||||
}
|
||||
|
||||
impl NSRange {
|
||||
#[inline]
|
||||
pub fn new(location: NSUInteger, length: NSUInteger) -> NSRange {
|
||||
NSRange { location, length }
|
||||
}
|
||||
}
|
||||
|
||||
fn nsstring_as_str(nsstr: &objc::runtime::Object) -> &str {
|
||||
let bytes = unsafe {
|
||||
let bytes: *const std::os::raw::c_char = msg_send![nsstr, UTF8String];
|
||||
bytes as *const u8
|
||||
};
|
||||
let len: NSUInteger = unsafe { msg_send![nsstr, length] };
|
||||
unsafe {
|
||||
let bytes = std::slice::from_raw_parts(bytes, len as usize);
|
||||
std::str::from_utf8(bytes).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn nsstring_from_str(string: &str) -> *mut objc::runtime::Object {
|
||||
const UTF8_ENCODING: usize = 4;
|
||||
|
||||
let cls = class!(NSString);
|
||||
let bytes = string.as_ptr() as *const c_void;
|
||||
unsafe {
|
||||
let obj: *mut objc::runtime::Object = msg_send![cls, alloc];
|
||||
let obj: *mut objc::runtime::Object = msg_send![
|
||||
obj,
|
||||
initWithBytes:bytes
|
||||
length:string.len()
|
||||
encoding:UTF8_ENCODING
|
||||
];
|
||||
let _: *mut c_void = msg_send![obj, autorelease];
|
||||
obj
|
||||
}
|
||||
}
|
||||
|
||||
/// Define a Rust wrapper for an Objective-C opaque type.
|
||||
///
|
||||
/// This macro adapts the `foreign-types` crate's [`foreign_type!`]
|
||||
/// macro to Objective-C, defining Rust types that represent owned and
|
||||
/// borrowed forms of some underlying Objective-C type, using
|
||||
/// Objective-C's reference counting to manage its lifetime.
|
||||
///
|
||||
/// Given a use of the form:
|
||||
///
|
||||
/// ```ignore
|
||||
/// foreign_obj_type! {
|
||||
/// type CType = MTLBuffer; // underlying Objective-C type
|
||||
/// pub struct Buffer; // owned Rust type
|
||||
/// pub struct BufferRef; // borrowed Rust type
|
||||
/// type ParentType = ResourceRef; // borrowed parent class
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This defines the types `Buffer` and `BufferRef` as owning and
|
||||
/// non-owning types, analogous to `String` and `str`, that manage
|
||||
/// some underlying `*mut MTLBuffer`:
|
||||
///
|
||||
/// - Both `Buffer` and `BufferRef` implement [`obj::Message`], indicating
|
||||
/// that they can be sent Objective-C messages.
|
||||
///
|
||||
/// - Dropping a `Buffer` sends the underlying `MTLBuffer` a `release`
|
||||
/// message, and cloning a `BufferRef` sends a `retain` message and
|
||||
/// returns a new `Buffer`.
|
||||
///
|
||||
/// - `Buffer` dereferences to `BufferRef`.
|
||||
///
|
||||
/// - `BufferRef` dereferences to its parent type `ResourceRef`. The
|
||||
/// `ParentType` component is optional; if omitted, the `Ref` type
|
||||
/// doesn't implement `Deref` or `DerefMut`.
|
||||
///
|
||||
/// - Both `Buffer` and `BufferRef` implement `std::fmt::Debug`,
|
||||
/// sending an Objective-C `debugDescription` message to the
|
||||
/// underlying `MTLBuffer`.
|
||||
///
|
||||
/// Following the `foreign_types` crate's nomenclature, the `Ref`
|
||||
/// suffix indicates that `BufferRef` and `ResourceRef` are non-owning
|
||||
/// types, used *by reference*, like `&BufferRef` or `&ResourceRef`.
|
||||
/// These types are not, themselves, references.
|
||||
macro_rules! foreign_obj_type {
|
||||
{
|
||||
type CType = $raw_ident:ident;
|
||||
pub struct $owned_ident:ident;
|
||||
type ParentType = $parent_ident:ident;
|
||||
} => {
|
||||
foreign_obj_type! {
|
||||
type CType = $raw_ident;
|
||||
pub struct $owned_ident;
|
||||
}
|
||||
|
||||
impl ::std::ops::Deref for paste!{[<$owned_ident Ref>]} {
|
||||
type Target = paste!{[<$parent_ident Ref>]};
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { &*(self as *const Self as *const Self::Target) }
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::convert::From<$owned_ident> for $parent_ident {
|
||||
fn from(item: $owned_ident) -> Self {
|
||||
unsafe { Self::from_ptr(::std::mem::transmute(item.into_ptr())) }
|
||||
}
|
||||
}
|
||||
};
|
||||
{
|
||||
type CType = $raw_ident:ident;
|
||||
pub struct $owned_ident:ident;
|
||||
} => {
|
||||
foreign_type! {
|
||||
pub unsafe type $owned_ident: Sync + Send {
|
||||
type CType = $raw_ident;
|
||||
fn drop = crate::obj_drop;
|
||||
fn clone = crate::obj_clone;
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl ::objc::Message for $raw_ident {
|
||||
}
|
||||
unsafe impl ::objc::Message for paste!{[<$owned_ident Ref>]} {
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for paste!{[<$owned_ident Ref>]} {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
unsafe {
|
||||
let string: *mut ::objc::runtime::Object = msg_send![self, debugDescription];
|
||||
write!(f, "{}", crate::nsstring_as_str(&*string))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for $owned_ident {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
::std::ops::Deref::deref(self).fmt(f)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! try_objc {
|
||||
{
|
||||
$err_name: ident => $body:expr
|
||||
} => {
|
||||
{
|
||||
let mut $err_name: *mut Object = ::std::ptr::null_mut();
|
||||
let value = $body;
|
||||
if !$err_name.is_null() {
|
||||
let desc: *mut Object = msg_send![$err_name, localizedDescription];
|
||||
let compile_error: *const std::os::raw::c_char = msg_send![desc, UTF8String];
|
||||
let message = CStr::from_ptr(compile_error).to_string_lossy().into_owned();
|
||||
return Err(message);
|
||||
}
|
||||
value
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! msg_send_bool {
|
||||
($obj:expr, $name:ident) => {{
|
||||
match msg_send![$obj, $name] {
|
||||
YES => true,
|
||||
NO => false,
|
||||
#[cfg(not(target_arch = "aarch64"))]
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}};
|
||||
($obj:expr, $name:ident : $arg:expr) => {{
|
||||
match msg_send![$obj, $name: $arg] {
|
||||
YES => true,
|
||||
NO => false,
|
||||
#[cfg(not(target_arch = "aarch64"))]
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! msg_send_bool_error_check {
|
||||
($obj:expr, $name:ident: $arg:expr) => {{
|
||||
let mut err: *mut Object = ptr::null_mut();
|
||||
let result: BOOL = msg_send![$obj, $name:$arg
|
||||
error:&mut err];
|
||||
if !err.is_null() {
|
||||
let desc: *mut Object = msg_send![err, localizedDescription];
|
||||
let c_msg: *const c_char = msg_send![desc, UTF8String];
|
||||
let message = CStr::from_ptr(c_msg).to_string_lossy().into_owned();
|
||||
Err(message)
|
||||
} else {
|
||||
match result {
|
||||
YES => Ok(true),
|
||||
NO => Ok(false),
|
||||
#[cfg(not(target_arch = "aarch64"))]
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/foundation/nsarray>
|
||||
pub struct NSArray<T> {
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
pub struct Array<T>(*mut NSArray<T>)
|
||||
where
|
||||
T: ForeignType + 'static,
|
||||
T::Ref: objc::Message + 'static;
|
||||
|
||||
pub struct ArrayRef<T>(foreign_types::Opaque, PhantomData<T>)
|
||||
where
|
||||
T: ForeignType + 'static,
|
||||
T::Ref: objc::Message + 'static;
|
||||
|
||||
impl<T> Drop for Array<T>
|
||||
where
|
||||
T: ForeignType + 'static,
|
||||
T::Ref: objc::Message + 'static,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let () = msg_send![self.0, release];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for Array<T>
|
||||
where
|
||||
T: ForeignType + 'static,
|
||||
T::Ref: objc::Message + 'static,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
unsafe { Array(msg_send![self.0, retain]) }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> objc::Message for NSArray<T>
|
||||
where
|
||||
T: ForeignType + 'static,
|
||||
T::Ref: objc::Message + 'static,
|
||||
{
|
||||
}
|
||||
|
||||
unsafe impl<T> objc::Message for ArrayRef<T>
|
||||
where
|
||||
T: ForeignType + 'static,
|
||||
T::Ref: objc::Message + 'static,
|
||||
{
|
||||
}
|
||||
|
||||
impl<T> Array<T>
|
||||
where
|
||||
T: ForeignType + 'static,
|
||||
T::Ref: objc::Message + 'static,
|
||||
{
|
||||
pub fn from_slice<'a>(s: &[&T::Ref]) -> &'a ArrayRef<T> {
|
||||
unsafe {
|
||||
let class = class!(NSArray);
|
||||
msg_send![class, arrayWithObjects: s.as_ptr() count: s.len()]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_owned_slice<'a>(s: &[T]) -> &'a ArrayRef<T> {
|
||||
unsafe {
|
||||
let class = class!(NSArray);
|
||||
msg_send![class, arrayWithObjects: s.as_ptr() count: s.len()]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> foreign_types::ForeignType for Array<T>
|
||||
where
|
||||
T: ForeignType + 'static,
|
||||
T::Ref: objc::Message + 'static,
|
||||
{
|
||||
type CType = NSArray<T>;
|
||||
type Ref = ArrayRef<T>;
|
||||
|
||||
unsafe fn from_ptr(p: *mut NSArray<T>) -> Self {
|
||||
Array(p)
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *mut NSArray<T> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> foreign_types::ForeignTypeRef for ArrayRef<T>
|
||||
where
|
||||
T: ForeignType + 'static,
|
||||
T::Ref: objc::Message + 'static,
|
||||
{
|
||||
type CType = NSArray<T>;
|
||||
}
|
||||
|
||||
impl<T> Deref for Array<T>
|
||||
where
|
||||
T: ForeignType + 'static,
|
||||
T::Ref: objc::Message + 'static,
|
||||
{
|
||||
type Target = ArrayRef<T>;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &ArrayRef<T> {
|
||||
unsafe { mem::transmute(self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Borrow<ArrayRef<T>> for Array<T>
|
||||
where
|
||||
T: ForeignType + 'static,
|
||||
T::Ref: objc::Message + 'static,
|
||||
{
|
||||
fn borrow(&self) -> &ArrayRef<T> {
|
||||
unsafe { mem::transmute(self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ToOwned for ArrayRef<T>
|
||||
where
|
||||
T: ForeignType + 'static,
|
||||
T::Ref: objc::Message + 'static,
|
||||
{
|
||||
type Owned = Array<T>;
|
||||
|
||||
fn to_owned(&self) -> Array<T> {
|
||||
unsafe { Array::from_ptr(msg_send![self, retain]) }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/quartzcore/cametaldrawable>
|
||||
pub enum CAMetalDrawable {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = CAMetalDrawable;
|
||||
pub struct MetalDrawable;
|
||||
type ParentType = Drawable;
|
||||
}
|
||||
|
||||
impl MetalDrawableRef {
|
||||
pub fn texture(&self) -> &TextureRef {
|
||||
unsafe { msg_send![self, texture] }
|
||||
}
|
||||
}
|
||||
|
||||
pub enum NSObject {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = NSObject;
|
||||
pub struct NsObject;
|
||||
}
|
||||
|
||||
impl NsObjectRef {
|
||||
pub fn conforms_to_protocol<T>(&self) -> Result<bool, String> {
|
||||
let name = ::std::any::type_name::<T>();
|
||||
if let Some(name) = name.split("::").last() {
|
||||
if let Some(protocol) = objc::runtime::Protocol::get(name) {
|
||||
Ok(unsafe { msg_send![self, conformsToProtocol: protocol] })
|
||||
} else {
|
||||
Err(format!("Can not find the protocol for type: {}.", name))
|
||||
}
|
||||
} else {
|
||||
Err(format!("Unexpected type name: {}.", name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See <https://developer.apple.com/documentation/quartzcore/cametallayer>
|
||||
pub enum CAMetalLayer {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = CAMetalLayer;
|
||||
pub struct MetalLayer;
|
||||
}
|
||||
|
||||
impl MetalLayer {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(CAMetalLayer);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MetalLayerRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
|
||||
pub fn set_device(&self, device: &DeviceRef) {
|
||||
unsafe { msg_send![self, setDevice: device] }
|
||||
}
|
||||
|
||||
pub fn pixel_format(&self) -> MTLPixelFormat {
|
||||
unsafe { msg_send![self, pixelFormat] }
|
||||
}
|
||||
|
||||
pub fn set_pixel_format(&self, pixel_format: MTLPixelFormat) {
|
||||
unsafe { msg_send![self, setPixelFormat: pixel_format] }
|
||||
}
|
||||
|
||||
pub fn drawable_size(&self) -> CGSize {
|
||||
unsafe { msg_send![self, drawableSize] }
|
||||
}
|
||||
|
||||
pub fn set_drawable_size(&self, size: CGSize) {
|
||||
unsafe { msg_send![self, setDrawableSize: size] }
|
||||
}
|
||||
|
||||
pub fn presents_with_transaction(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, presentsWithTransaction] }
|
||||
}
|
||||
|
||||
pub fn set_presents_with_transaction(&self, transaction: bool) {
|
||||
unsafe { msg_send![self, setPresentsWithTransaction: transaction] }
|
||||
}
|
||||
|
||||
pub fn display_sync_enabled(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, displaySyncEnabled] }
|
||||
}
|
||||
|
||||
pub fn set_display_sync_enabled(&self, enabled: bool) {
|
||||
unsafe { msg_send![self, setDisplaySyncEnabled: enabled] }
|
||||
}
|
||||
|
||||
pub fn maximum_drawable_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, maximumDrawableCount] }
|
||||
}
|
||||
|
||||
pub fn set_maximum_drawable_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setMaximumDrawableCount: count] }
|
||||
}
|
||||
|
||||
pub fn set_edge_antialiasing_mask(&self, mask: u64) {
|
||||
unsafe { msg_send![self, setEdgeAntialiasingMask: mask] }
|
||||
}
|
||||
|
||||
pub fn set_masks_to_bounds(&self, masks: bool) {
|
||||
unsafe { msg_send![self, setMasksToBounds: masks] }
|
||||
}
|
||||
|
||||
pub fn remove_all_animations(&self) {
|
||||
unsafe { msg_send![self, removeAllAnimations] }
|
||||
}
|
||||
|
||||
pub fn next_drawable(&self) -> Option<&MetalDrawableRef> {
|
||||
unsafe { msg_send![self, nextDrawable] }
|
||||
}
|
||||
|
||||
pub fn contents_scale(&self) -> CGFloat {
|
||||
unsafe { msg_send![self, contentsScale] }
|
||||
}
|
||||
|
||||
pub fn set_contents_scale(&self, scale: CGFloat) {
|
||||
unsafe { msg_send![self, setContentsScale: scale] }
|
||||
}
|
||||
|
||||
/// [framebufferOnly Apple Docs](https://developer.apple.com/documentation/metal/mtltexture/1515749-framebufferonly?language=objc)
|
||||
pub fn framebuffer_only(&self) -> bool {
|
||||
unsafe { msg_send_bool!(self, framebufferOnly) }
|
||||
}
|
||||
|
||||
pub fn set_framebuffer_only(&self, framebuffer_only: bool) {
|
||||
unsafe { msg_send![self, setFramebufferOnly: framebuffer_only] }
|
||||
}
|
||||
|
||||
pub fn is_opaque(&self) -> bool {
|
||||
unsafe { msg_send_bool!(self, isOpaque) }
|
||||
}
|
||||
|
||||
pub fn set_opaque(&self, opaque: bool) {
|
||||
unsafe { msg_send![self, setOpaque: opaque] }
|
||||
}
|
||||
|
||||
pub fn wants_extended_dynamic_range_content(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, wantsExtendedDynamicRangeContent] }
|
||||
}
|
||||
|
||||
pub fn set_wants_extended_dynamic_range_content(
|
||||
&self,
|
||||
wants_extended_dynamic_range_content: bool,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
setWantsExtendedDynamicRangeContent: wants_extended_dynamic_range_content
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod accelerator_structure;
|
||||
mod argument;
|
||||
mod buffer;
|
||||
mod capturedescriptor;
|
||||
mod capturemanager;
|
||||
mod commandbuffer;
|
||||
mod commandqueue;
|
||||
mod computepass;
|
||||
mod constants;
|
||||
mod counters;
|
||||
mod depthstencil;
|
||||
mod device;
|
||||
mod drawable;
|
||||
mod encoder;
|
||||
mod heap;
|
||||
mod indirect_encoder;
|
||||
mod library;
|
||||
#[cfg(feature = "mps")]
|
||||
pub mod mps;
|
||||
mod pipeline;
|
||||
mod renderpass;
|
||||
mod resource;
|
||||
mod sampler;
|
||||
mod sync;
|
||||
mod texture;
|
||||
mod types;
|
||||
mod vertexdescriptor;
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub use {
|
||||
accelerator_structure::*,
|
||||
argument::*,
|
||||
buffer::*,
|
||||
counters::*,
|
||||
computepass::*,
|
||||
capturedescriptor::*,
|
||||
capturemanager::*,
|
||||
commandbuffer::*,
|
||||
commandqueue::*,
|
||||
constants::*,
|
||||
depthstencil::*,
|
||||
device::*,
|
||||
drawable::*,
|
||||
encoder::*,
|
||||
heap::*,
|
||||
indirect_encoder::*,
|
||||
library::*,
|
||||
pipeline::*,
|
||||
renderpass::*,
|
||||
resource::*,
|
||||
sampler::*,
|
||||
texture::*,
|
||||
types::*,
|
||||
vertexdescriptor::*,
|
||||
sync::*,
|
||||
};
|
||||
|
||||
#[inline]
|
||||
unsafe fn obj_drop<T>(p: *mut T) {
|
||||
msg_send![(p as *mut Object), release]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn obj_clone<T: 'static>(p: *mut T) -> *mut T {
|
||||
msg_send![(p as *mut Object), retain]
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type c_size_t = usize;
|
||||
|
||||
// TODO: expand supported interface
|
||||
/// See <https://developer.apple.com/documentation/foundation/nsurl>
|
||||
pub enum NSURL {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = NSURL;
|
||||
pub struct URL;
|
||||
}
|
||||
|
||||
impl URL {
|
||||
pub fn new_with_string(string: &str) -> Self {
|
||||
unsafe {
|
||||
let ns_str = crate::nsstring_from_str(string);
|
||||
let class = class!(NSURL);
|
||||
msg_send![class, URLWithString: ns_str]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl URLRef {
|
||||
pub fn absolute_string(&self) -> &str {
|
||||
unsafe {
|
||||
let absolute_string = msg_send![self, absoluteString];
|
||||
crate::nsstring_as_str(absolute_string)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &str {
|
||||
unsafe {
|
||||
let path = msg_send![self, path];
|
||||
crate::nsstring_as_str(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
901
third-party/vendor/metal/src/library.rs
vendored
Normal file
901
third-party/vendor/metal/src/library.rs
vendored
Normal file
|
|
@ -0,0 +1,901 @@
|
|||
// Copyright 2017 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
|
||||
use foreign_types::ForeignType;
|
||||
use objc::runtime::{Object, BOOL, NO, YES};
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::{c_char, c_void};
|
||||
use std::ptr;
|
||||
|
||||
/// Only available on (macos(10.12), ios(10.0)
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlpatchtype/>
|
||||
#[repr(u64)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum MTLPatchType {
|
||||
None = 0,
|
||||
Triangle = 1,
|
||||
Quad = 2,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlvertexattribute/>
|
||||
pub enum MTLVertexAttribute {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLVertexAttribute;
|
||||
pub struct VertexAttribute;
|
||||
}
|
||||
|
||||
impl VertexAttributeRef {
|
||||
pub fn name(&self) -> &str {
|
||||
unsafe {
|
||||
let name = msg_send![self, name];
|
||||
crate::nsstring_as_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attribute_index(&self) -> u64 {
|
||||
unsafe { msg_send![self, attributeIndex] }
|
||||
}
|
||||
|
||||
pub fn attribute_type(&self) -> MTLDataType {
|
||||
unsafe { msg_send![self, attributeType] }
|
||||
}
|
||||
|
||||
pub fn is_active(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isActive] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.12), ios(10.0)
|
||||
pub fn is_patch_data(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isPatchData] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.12), ios(10.0)
|
||||
pub fn is_patch_control_point_data(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isPatchControlPointData] }
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.12), ios(10.0))
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlattribute/>
|
||||
pub enum MTLAttribute {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLAttribute;
|
||||
pub struct Attribute;
|
||||
}
|
||||
|
||||
impl AttributeRef {
|
||||
pub fn name(&self) -> &str {
|
||||
unsafe {
|
||||
let name = msg_send![self, name];
|
||||
crate::nsstring_as_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attribute_index(&self) -> u64 {
|
||||
unsafe { msg_send![self, attributeIndex] }
|
||||
}
|
||||
|
||||
pub fn attribute_type(&self) -> MTLDataType {
|
||||
unsafe { msg_send![self, attributeType] }
|
||||
}
|
||||
|
||||
pub fn is_active(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isActive] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.12), ios(10.0))
|
||||
pub fn is_patch_data(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isPatchData] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.12), ios(10.0))
|
||||
pub fn is_patch_control_point_data(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isPatchControlPointData] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlfunctiontype/>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLFunctionType {
|
||||
Vertex = 1,
|
||||
Fragment = 2,
|
||||
Kernel = 3,
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
Visible = 5,
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
Intersection = 6,
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.12), ios(10.0))
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlfunctionconstant/>
|
||||
pub enum MTLFunctionConstant {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLFunctionConstant;
|
||||
pub struct FunctionConstant;
|
||||
}
|
||||
|
||||
impl FunctionConstantRef {
|
||||
pub fn name(&self) -> &str {
|
||||
unsafe {
|
||||
let name = msg_send![self, name];
|
||||
crate::nsstring_as_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data_type(&self) -> MTLDataType {
|
||||
unsafe { msg_send![self, type] }
|
||||
}
|
||||
|
||||
pub fn index(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, index] }
|
||||
}
|
||||
|
||||
pub fn required(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, required] }
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlfunctionoptions/>
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct MTLFunctionOptions: NSUInteger {
|
||||
const None = 0;
|
||||
const CompileToBinary = 1 << 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlfunctiondescriptor/>
|
||||
pub enum MTLFunctionDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLFunctionDescriptor;
|
||||
pub struct FunctionDescriptor;
|
||||
}
|
||||
|
||||
impl FunctionDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLFunctionDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FunctionDescriptorRef {
|
||||
pub fn name(&self) -> &str {
|
||||
unsafe {
|
||||
let name = msg_send![self, name];
|
||||
crate::nsstring_as_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_name(&self, name: &str) {
|
||||
unsafe {
|
||||
let ns_name = crate::nsstring_from_str(name);
|
||||
let () = msg_send![self, setName: ns_name];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn specialized_name(&self) -> &str {
|
||||
unsafe {
|
||||
let name = msg_send![self, specializedName];
|
||||
crate::nsstring_as_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_specialized_name(&self, name: &str) {
|
||||
unsafe {
|
||||
let ns_name = crate::nsstring_from_str(name);
|
||||
let () = msg_send![self, setSpecializedName: ns_name];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn constant_values(&self) -> &FunctionConstantValuesRef {
|
||||
unsafe { msg_send![self, constantValues] }
|
||||
}
|
||||
|
||||
pub fn set_constant_values(&self, values: &FunctionConstantValuesRef) {
|
||||
unsafe { msg_send![self, setConstantValues: values] }
|
||||
}
|
||||
|
||||
pub fn options(&self) -> MTLFunctionOptions {
|
||||
unsafe { msg_send![self, options] }
|
||||
}
|
||||
|
||||
pub fn set_options(&self, options: MTLFunctionOptions) {
|
||||
unsafe { msg_send![self, setOptions: options] }
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlintersectionfunctiondescriptor/>
|
||||
pub enum MTLIntersectionFunctionDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLIntersectionFunctionDescriptor;
|
||||
pub struct IntersectionFunctionDescriptor;
|
||||
type ParentType = FunctionDescriptor;
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlfunctionhandle/>
|
||||
pub enum MTLFunctionHandle {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLFunctionHandle;
|
||||
pub struct FunctionHandle;
|
||||
}
|
||||
|
||||
impl FunctionHandleRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
unsafe {
|
||||
let ns_name = msg_send![self, name];
|
||||
crate::nsstring_as_str(ns_name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn function_type(&self) -> MTLFunctionType {
|
||||
unsafe { msg_send![self, functionType] }
|
||||
}
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// MTLVisibleFunctionTableDescriptor
|
||||
// MTLVisibleFunctionTable
|
||||
// MTLIntersectionFunctionSignature
|
||||
// MTLIntersectionFunctionTableDescriptor
|
||||
// MTLIntersectionFunctionTable
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlfunction/>
|
||||
pub enum MTLFunction {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLFunction;
|
||||
pub struct Function;
|
||||
}
|
||||
|
||||
impl FunctionRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.12), ios(10.0))
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let ns_label = msg_send![self, label];
|
||||
crate::nsstring_as_str(ns_label)
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.12), ios(10.0))
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let ns_label = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: ns_label];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
unsafe {
|
||||
let name = msg_send![self, name];
|
||||
crate::nsstring_as_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn function_type(&self) -> MTLFunctionType {
|
||||
unsafe { msg_send![self, functionType] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.12), ios(10.0))
|
||||
pub fn patch_type(&self) -> MTLPatchType {
|
||||
unsafe { msg_send![self, patchType] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.12), ios(10.0))
|
||||
pub fn patch_control_point_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, patchControlPointCount] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.12), ios(10.0))
|
||||
pub fn vertex_attributes(&self) -> &Array<VertexAttribute> {
|
||||
unsafe { msg_send![self, vertexAttributes] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.12), ios(10.0))
|
||||
pub fn stage_input_attributes(&self) -> &Array<Attribute> {
|
||||
unsafe { msg_send![self, stageInputAttributes] }
|
||||
}
|
||||
|
||||
pub fn new_argument_encoder(&self, buffer_index: NSUInteger) -> ArgumentEncoder {
|
||||
unsafe {
|
||||
let ptr = msg_send![self, newArgumentEncoderWithBufferIndex: buffer_index];
|
||||
ArgumentEncoder::from_ptr(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn function_constants_dictionary(&self) -> *mut Object {
|
||||
unsafe { msg_send![self, functionConstantsDictionary] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
pub fn options(&self) -> MTLFunctionOptions {
|
||||
unsafe { msg_send![self, options] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtllanguageversion/>
|
||||
#[repr(u64)]
|
||||
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum MTLLanguageVersion {
|
||||
V1_0 = 0x10000,
|
||||
V1_1 = 0x10001,
|
||||
V1_2 = 0x10002,
|
||||
V2_0 = 0x20000,
|
||||
V2_1 = 0x20001,
|
||||
V2_2 = 0x20002,
|
||||
/// available on macOS 11.0+, iOS 14.0+
|
||||
V2_3 = 0x20003,
|
||||
/// available on macOS 12.0+, iOS 15.0+
|
||||
V2_4 = 0x20004,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlfunctionconstantvalues/>
|
||||
pub enum MTLFunctionConstantValues {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLFunctionConstantValues;
|
||||
pub struct FunctionConstantValues;
|
||||
}
|
||||
|
||||
impl FunctionConstantValues {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLFunctionConstantValues);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FunctionConstantValuesRef {
|
||||
pub fn set_constant_value_at_index(
|
||||
&self,
|
||||
value: *const c_void,
|
||||
ty: MTLDataType,
|
||||
index: NSUInteger,
|
||||
) {
|
||||
unsafe { msg_send![self, setConstantValue:value type:ty atIndex:index] }
|
||||
}
|
||||
|
||||
pub fn set_constant_values_with_range(
|
||||
&self,
|
||||
values: *const c_void,
|
||||
ty: MTLDataType,
|
||||
range: NSRange,
|
||||
) {
|
||||
unsafe { msg_send![self, setConstantValues:values type:ty withRange:range] }
|
||||
}
|
||||
|
||||
pub fn set_constant_value_with_name(&self, value: *const c_void, ty: MTLDataType, name: &str) {
|
||||
unsafe {
|
||||
let ns_name = crate::nsstring_from_str(name);
|
||||
msg_send![self, setConstantValue:value type:ty withName:ns_name]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtllibrarytype/>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLLibraryType {
|
||||
Executable = 0,
|
||||
Dynamic = 1,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcompileoptions/>
|
||||
pub enum MTLCompileOptions {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLCompileOptions;
|
||||
pub struct CompileOptions;
|
||||
}
|
||||
|
||||
impl CompileOptions {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLCompileOptions);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CompileOptionsRef {
|
||||
pub unsafe fn preprocessor_macros(&self) -> *mut Object {
|
||||
msg_send![self, preprocessorMacros]
|
||||
}
|
||||
|
||||
pub unsafe fn set_preprocessor_macros(&self, defines: *mut Object) {
|
||||
msg_send![self, setPreprocessorMacros: defines]
|
||||
}
|
||||
|
||||
pub fn is_fast_math_enabled(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, fastMathEnabled] }
|
||||
}
|
||||
|
||||
pub fn set_fast_math_enabled(&self, enabled: bool) {
|
||||
unsafe { msg_send![self, setFastMathEnabled: enabled] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.11), ios(9.0))
|
||||
pub fn language_version(&self) -> MTLLanguageVersion {
|
||||
unsafe { msg_send![self, languageVersion] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(10.11), ios(9.0))
|
||||
pub fn set_language_version(&self, version: MTLLanguageVersion) {
|
||||
unsafe { msg_send![self, setLanguageVersion: version] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
pub fn library_type(&self) -> MTLLibraryType {
|
||||
unsafe { msg_send![self, libraryType] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
pub fn set_library_type(&self, lib_type: MTLLibraryType) {
|
||||
unsafe { msg_send![self, setLibraryType: lib_type] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
pub fn install_name(&self) -> &str {
|
||||
unsafe {
|
||||
let name = msg_send![self, installName];
|
||||
crate::nsstring_as_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
pub fn set_install_name(&self, name: &str) {
|
||||
unsafe {
|
||||
let install_name = crate::nsstring_from_str(name);
|
||||
let () = msg_send![self, setInstallName: install_name];
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
///
|
||||
/// Marshal to Rust Vec
|
||||
pub fn libraries(&self) -> Vec<DynamicLibrary> {
|
||||
unsafe {
|
||||
let libraries: *mut Object = msg_send![self, libraries];
|
||||
let count: NSUInteger = msg_send![libraries, count];
|
||||
let ret = (0..count)
|
||||
.map(|i| {
|
||||
let lib = msg_send![libraries, objectAtIndex: i];
|
||||
DynamicLibrary::from_ptr(lib)
|
||||
})
|
||||
.collect();
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
///
|
||||
/// As raw NSArray
|
||||
pub fn libraries_as_nsarray(&self) -> &ArrayRef<DynamicLibrary> {
|
||||
unsafe { msg_send![self, libraries] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
///
|
||||
/// Marshal from Rust slice
|
||||
pub fn set_libraries(&self, libraries: &[&DynamicLibraryRef]) {
|
||||
let ns_array = Array::<DynamicLibrary>::from_slice(libraries);
|
||||
unsafe { msg_send![self, setLibraries: ns_array] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
///
|
||||
/// From raw NSArray
|
||||
pub fn set_libraries_nsarray(&self, libraries: &ArrayRef<DynamicLibrary>) {
|
||||
unsafe { msg_send![self, setLibraries: libraries] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), macCatalyst(14.0), ios(13.0))
|
||||
pub fn preserve_invariance(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, preserveInvariance] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), macCatalyst(14.0), ios(13.0))
|
||||
pub fn set_preserve_invariance(&self, preserve: bool) {
|
||||
unsafe { msg_send![self, setPreserveInvariance: preserve] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtllibraryerror/>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLLibraryError {
|
||||
Unsupported = 1,
|
||||
Internal = 2,
|
||||
CompileFailure = 3,
|
||||
CompileWarning = 4,
|
||||
/// Only available on (macos(10.12), ios(10.0))
|
||||
FunctionNotFound = 5,
|
||||
/// Only available on (macos(10.12), ios(10.0))
|
||||
FileNotFound = 6,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtllibrary/>
|
||||
pub enum MTLLibrary {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLLibrary;
|
||||
pub struct Library;
|
||||
}
|
||||
|
||||
impl LibraryRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: should rename to new_function
|
||||
pub fn get_function(
|
||||
&self,
|
||||
name: &str,
|
||||
constants: Option<FunctionConstantValues>,
|
||||
) -> Result<Function, String> {
|
||||
unsafe {
|
||||
let nsname = crate::nsstring_from_str(name);
|
||||
|
||||
let function: *mut MTLFunction = match constants {
|
||||
Some(c) => try_objc! { err => msg_send![self,
|
||||
newFunctionWithName: nsname.as_ref()
|
||||
constantValues: c.as_ref()
|
||||
error: &mut err
|
||||
]},
|
||||
None => msg_send![self, newFunctionWithName: nsname.as_ref()],
|
||||
};
|
||||
|
||||
if !function.is_null() {
|
||||
Ok(Function::from_ptr(function))
|
||||
} else {
|
||||
Err(format!("Function '{}' does not exist", name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: get_function_async with completion handler
|
||||
|
||||
pub fn function_names(&self) -> Vec<String> {
|
||||
unsafe {
|
||||
let names: *mut Object = msg_send![self, functionNames];
|
||||
let count: NSUInteger = msg_send![names, count];
|
||||
let ret = (0..count)
|
||||
.map(|i| {
|
||||
let name = msg_send![names, objectAtIndex: i];
|
||||
nsstring_as_str(name).to_string()
|
||||
})
|
||||
.collect();
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
pub fn library_type(&self) -> MTLLibraryType {
|
||||
unsafe { msg_send![self, type] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
pub fn install_name(&self) -> Option<&str> {
|
||||
unsafe {
|
||||
let maybe_name: *mut Object = msg_send![self, installName];
|
||||
maybe_name.as_ref().map(crate::nsstring_as_str)
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
pub fn new_function_with_descriptor(
|
||||
&self,
|
||||
descriptor: &FunctionDescriptorRef,
|
||||
) -> Result<Function, String> {
|
||||
unsafe {
|
||||
let function: *mut MTLFunction = try_objc! {
|
||||
err => msg_send![self,
|
||||
newFunctionWithDescriptor: descriptor
|
||||
error: &mut err
|
||||
]
|
||||
};
|
||||
|
||||
if !function.is_null() {
|
||||
Ok(Function::from_ptr(function))
|
||||
} else {
|
||||
Err(String::from("new_function_with_descriptor() failed"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
pub fn new_intersection_function_with_descriptor(
|
||||
&self,
|
||||
descriptor: &IntersectionFunctionDescriptorRef,
|
||||
) -> Result<Function, String> {
|
||||
unsafe {
|
||||
let function: *mut MTLFunction = try_objc! {
|
||||
err => msg_send![self,
|
||||
newIntersectionFunctionWithDescriptor: descriptor
|
||||
error: &mut err
|
||||
]
|
||||
};
|
||||
|
||||
if !function.is_null() {
|
||||
Ok(Function::from_ptr(function))
|
||||
} else {
|
||||
Err(String::from(
|
||||
"new_intersection_function_with_descriptor() failed",
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtldynamiclibraryerror/>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLDynamicLibraryError {
|
||||
None = 0,
|
||||
InvalidFile = 1,
|
||||
CompilationFailure = 2,
|
||||
UnresolvedInstallName = 3,
|
||||
DependencyLoadFailure = 4,
|
||||
Unsupported = 5,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtldynamiclibrary/>
|
||||
pub enum MTLDynamicLibrary {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLDynamicLibrary;
|
||||
pub struct DynamicLibrary;
|
||||
}
|
||||
|
||||
impl DynamicLibraryRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn install_name(&self) -> &str {
|
||||
unsafe {
|
||||
let name = msg_send![self, installName];
|
||||
crate::nsstring_as_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialize_to_url(&self, url: &URLRef) -> Result<bool, String> {
|
||||
unsafe { msg_send_bool_error_check![self, serializeToURL: url] }
|
||||
}
|
||||
}
|
||||
|
||||
/// macOS 11.0+ iOS 14.0+
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlbinaryarchivedescriptor/>
|
||||
pub enum MTLBinaryArchiveDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLBinaryArchiveDescriptor;
|
||||
pub struct BinaryArchiveDescriptor;
|
||||
}
|
||||
|
||||
impl BinaryArchiveDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLBinaryArchiveDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BinaryArchiveDescriptorRef {
|
||||
pub fn url(&self) -> &URLRef {
|
||||
unsafe { msg_send![self, url] }
|
||||
}
|
||||
pub fn set_url(&self, url: &URLRef) {
|
||||
unsafe { msg_send![self, setUrl: url] }
|
||||
}
|
||||
}
|
||||
|
||||
/// macOS 11.0+ iOS 14.0+
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlbinaryarchive/>
|
||||
pub enum MTLBinaryArchive {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLBinaryArchive;
|
||||
pub struct BinaryArchive;
|
||||
}
|
||||
|
||||
impl BinaryArchiveRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_compute_pipeline_functions_with_descriptor(
|
||||
&self,
|
||||
descriptor: &ComputePipelineDescriptorRef,
|
||||
) -> Result<bool, String> {
|
||||
unsafe {
|
||||
msg_send_bool_error_check![self, addComputePipelineFunctionsWithDescriptor: descriptor]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_render_pipeline_functions_with_descriptor(
|
||||
&self,
|
||||
descriptor: &RenderPipelineDescriptorRef,
|
||||
) -> Result<bool, String> {
|
||||
unsafe {
|
||||
msg_send_bool_error_check![self, addRenderPipelineFunctionsWithDescriptor: descriptor]
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: addTileRenderPipelineFunctionsWithDescriptor
|
||||
// - (BOOL)addTileRenderPipelineFunctionsWithDescriptor:(MTLTileRenderPipelineDescriptor *)descriptor
|
||||
// error:(NSError * _Nullable *)error;
|
||||
|
||||
pub fn serialize_to_url(&self, url: &URLRef) -> Result<bool, String> {
|
||||
unsafe {
|
||||
let mut err: *mut Object = ptr::null_mut();
|
||||
let result: BOOL = msg_send![self, serializeToURL:url
|
||||
error:&mut err];
|
||||
if !err.is_null() {
|
||||
// FIXME: copy pasta
|
||||
let desc: *mut Object = msg_send![err, localizedDescription];
|
||||
let c_msg: *const c_char = msg_send![desc, UTF8String];
|
||||
let message = CStr::from_ptr(c_msg).to_string_lossy().into_owned();
|
||||
Err(message)
|
||||
} else {
|
||||
match result {
|
||||
YES => Ok(true),
|
||||
NO => Ok(false),
|
||||
#[cfg(not(target_arch = "aarch64"))]
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// macOS 11.0+ iOS 14.0+
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtllinkedfunctions/>
|
||||
pub enum MTLLinkedFunctions {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLLinkedFunctions;
|
||||
pub struct LinkedFunctions;
|
||||
}
|
||||
|
||||
impl LinkedFunctions {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLLinkedFunctions);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LinkedFunctionsRef {
|
||||
/// Marshal to Rust Vec
|
||||
pub fn functions(&self) -> Vec<Function> {
|
||||
unsafe {
|
||||
let functions: *mut Object = msg_send![self, functions];
|
||||
let count: NSUInteger = msg_send![functions, count];
|
||||
let ret = (0..count)
|
||||
.map(|i| {
|
||||
let f = msg_send![functions, objectAtIndex: i];
|
||||
Function::from_ptr(f)
|
||||
})
|
||||
.collect();
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// Marshal from Rust slice
|
||||
pub fn set_functions(&self, functions: &[&FunctionRef]) {
|
||||
let ns_array = Array::<Function>::from_slice(functions);
|
||||
unsafe { msg_send![self, setFunctions: ns_array] }
|
||||
}
|
||||
|
||||
/// Marshal to Rust Vec
|
||||
pub fn binary_functions(&self) -> Vec<Function> {
|
||||
unsafe {
|
||||
let functions: *mut Object = msg_send![self, binaryFunctions];
|
||||
let count: NSUInteger = msg_send![functions, count];
|
||||
let ret = (0..count)
|
||||
.map(|i| {
|
||||
let f = msg_send![functions, objectAtIndex: i];
|
||||
Function::from_ptr(f)
|
||||
})
|
||||
.collect();
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// Marshal from Rust slice
|
||||
pub fn set_binary_functions(&self, functions: &[&FunctionRef]) {
|
||||
let ns_array = Array::<Function>::from_slice(functions);
|
||||
unsafe { msg_send![self, setBinaryFunctions: ns_array] }
|
||||
}
|
||||
|
||||
// TODO: figure out NSDictionary wrapper
|
||||
// TODO: groups
|
||||
// @property (readwrite, nonatomic, copy, nullable) NSDictionary<NSString*, NSArray<id<MTLFunction>>*> *groups;
|
||||
}
|
||||
572
third-party/vendor/metal/src/mps.rs
vendored
Normal file
572
third-party/vendor/metal/src/mps.rs
vendored
Normal file
|
|
@ -0,0 +1,572 @@
|
|||
// Copyright 2020 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
|
||||
use objc::runtime::{BOOL, YES};
|
||||
|
||||
#[cfg_attr(feature = "link", link(name = "MetalPerformanceShaders", kind = "framework"))]
|
||||
extern "C" {
|
||||
fn MPSSupportsMTLDevice(device: *const std::ffi::c_void) -> BOOL;
|
||||
}
|
||||
|
||||
pub fn mps_supports_device(device: &DeviceRef) -> bool {
|
||||
let b: BOOL = unsafe {
|
||||
let ptr: *const DeviceRef = device;
|
||||
MPSSupportsMTLDevice(ptr as _)
|
||||
};
|
||||
b == YES
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpskernel>
|
||||
pub enum MPSKernel {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MPSKernel;
|
||||
pub struct Kernel;
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsraydatatype>
|
||||
pub enum MPSRayDataType {
|
||||
OriginDirection = 0,
|
||||
OriginMinDistanceDirectionMaxDistance = 1,
|
||||
OriginMaskDirectionMaxDistance = 2,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsraymaskoptions>
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct MPSRayMaskOptions: NSUInteger {
|
||||
/// Enable primitive masks
|
||||
const Primitive = 1;
|
||||
/// Enable instance masks
|
||||
const Instance = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/// Options that determine the data contained in an intersection result.
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsintersectiondatatype>
|
||||
pub enum MPSIntersectionDataType {
|
||||
Distance = 0,
|
||||
DistancePrimitiveIndex = 1,
|
||||
DistancePrimitiveIndexCoordinates = 2,
|
||||
DistancePrimitiveIndexInstanceIndex = 3,
|
||||
DistancePrimitiveIndexInstanceIndexCoordinates = 4,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsintersectiontype>
|
||||
pub enum MPSIntersectionType {
|
||||
/// Find the closest intersection to the ray's origin along the ray direction.
|
||||
/// This is potentially slower than `Any` but is well suited to primary visibility rays.
|
||||
Nearest = 0,
|
||||
/// Find any intersection along the ray direction. This is potentially faster than `Nearest` and
|
||||
/// is well suited to shadow and occlusion rays.
|
||||
Any = 1,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsraymaskoperator>
|
||||
pub enum MPSRayMaskOperator {
|
||||
/// Accept the intersection if `(primitive mask & ray mask) != 0`.
|
||||
And = 0,
|
||||
/// Accept the intersection if `~(primitive mask & ray mask) != 0`.
|
||||
NotAnd = 1,
|
||||
/// Accept the intersection if `(primitive mask | ray mask) != 0`.
|
||||
Or = 2,
|
||||
/// Accept the intersection if `~(primitive mask | ray mask) != 0`.
|
||||
NotOr = 3,
|
||||
/// Accept the intersection if `(primitive mask ^ ray mask) != 0`.
|
||||
/// Note that this is equivalent to the "!=" operator.
|
||||
Xor = 4,
|
||||
/// Accept the intersection if `~(primitive mask ^ ray mask) != 0`.
|
||||
/// Note that this is equivalent to the "==" operator.
|
||||
NotXor = 5,
|
||||
/// Accept the intersection if `(primitive mask < ray mask) != 0`.
|
||||
LessThan = 6,
|
||||
/// Accept the intersection if `(primitive mask <= ray mask) != 0`.
|
||||
LessThanOrEqualTo = 7,
|
||||
/// Accept the intersection if `(primitive mask > ray mask) != 0`.
|
||||
GreaterThan = 8,
|
||||
/// Accept the intersection if `(primitive mask >= ray mask) != 0`.
|
||||
GreaterThanOrEqualTo = 9,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpstriangleintersectiontesttype>
|
||||
pub enum MPSTriangleIntersectionTestType {
|
||||
/// Use the default ray/triangle intersection test
|
||||
Default = 0,
|
||||
/// Use a watertight ray/triangle intersection test which avoids gaps along shared triangle edges.
|
||||
/// Shared vertices may still have gaps.
|
||||
/// This intersection test may be slower than `Default`.
|
||||
Watertight = 1,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsaccelerationstructurestatus>
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MPSAccelerationStructureStatus {
|
||||
Unbuilt = 0,
|
||||
Built = 1,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsaccelerationstructureusage>
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct MPSAccelerationStructureUsage: NSUInteger {
|
||||
/// No usage options specified
|
||||
const None = 0;
|
||||
/// Option that enables support for refitting the acceleration structure after it has been built.
|
||||
const Refit = 1;
|
||||
/// Option indicating that the acceleration structure will be rebuilt frequently.
|
||||
const FrequentRebuild = 2;
|
||||
const PreferGPUBuild = 4;
|
||||
const PreferCPUBuild = 8;
|
||||
}
|
||||
}
|
||||
|
||||
/// A common bit for all floating point data types.
|
||||
const MPSDataTypeFloatBit: isize = 0x10000000;
|
||||
const MPSDataTypeSignedBit: isize = 0x20000000;
|
||||
const MPSDataTypeNormalizedBit: isize = 0x40000000;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsdatatype>
|
||||
pub enum MPSDataType {
|
||||
Invalid = 0,
|
||||
|
||||
Float32 = MPSDataTypeFloatBit | 32,
|
||||
Float16 = MPSDataTypeFloatBit | 16,
|
||||
|
||||
// Signed integers.
|
||||
Int8 = MPSDataTypeSignedBit | 8,
|
||||
Int16 = MPSDataTypeSignedBit | 16,
|
||||
Int32 = MPSDataTypeSignedBit | 32,
|
||||
|
||||
// Unsigned integers. Range: [0, UTYPE_MAX]
|
||||
UInt8 = 8,
|
||||
UInt16 = 16,
|
||||
UInt32 = 32,
|
||||
|
||||
// Unsigned normalized. Range: [0, 1.0]
|
||||
Unorm1 = MPSDataTypeNormalizedBit | 1,
|
||||
Unorm8 = MPSDataTypeNormalizedBit | 8,
|
||||
}
|
||||
|
||||
/// A kernel that performs intersection tests between rays and geometry.
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsrayintersector>
|
||||
pub enum MPSRayIntersector {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MPSRayIntersector;
|
||||
pub struct RayIntersector;
|
||||
type ParentType = Kernel;
|
||||
}
|
||||
|
||||
impl RayIntersector {
|
||||
pub fn from_device(device: &DeviceRef) -> Option<Self> {
|
||||
unsafe {
|
||||
let intersector: RayIntersector = msg_send![class!(MPSRayIntersector), alloc];
|
||||
let ptr: *mut Object = msg_send![intersector.as_ref(), initWithDevice: device];
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(intersector)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RayIntersectorRef {
|
||||
pub fn set_cull_mode(&self, mode: MTLCullMode) {
|
||||
unsafe { msg_send![self, setCullMode: mode] }
|
||||
}
|
||||
|
||||
pub fn set_front_facing_winding(&self, winding: MTLWinding) {
|
||||
unsafe { msg_send![self, setFrontFacingWinding: winding] }
|
||||
}
|
||||
|
||||
pub fn set_intersection_data_type(&self, options: MPSIntersectionDataType) {
|
||||
unsafe { msg_send![self, setIntersectionDataType: options] }
|
||||
}
|
||||
|
||||
pub fn set_intersection_stride(&self, stride: NSUInteger) {
|
||||
unsafe { msg_send![self, setIntersectionStride: stride] }
|
||||
}
|
||||
|
||||
pub fn set_ray_data_type(&self, ty: MPSRayDataType) {
|
||||
unsafe { msg_send![self, setRayDataType: ty] }
|
||||
}
|
||||
|
||||
pub fn set_ray_index_data_type(&self, ty: MPSDataType) {
|
||||
unsafe { msg_send![self, setRayIndexDataType: ty] }
|
||||
}
|
||||
|
||||
pub fn set_ray_mask(&self, ray_mask: u32) {
|
||||
unsafe { msg_send![self, setRayMask: ray_mask] }
|
||||
}
|
||||
|
||||
pub fn set_ray_mask_operator(&self, operator: MPSRayMaskOperator) {
|
||||
unsafe { msg_send![self, setRayMaskOperator: operator] }
|
||||
}
|
||||
|
||||
pub fn set_ray_mask_options(&self, options: MPSRayMaskOptions) {
|
||||
unsafe { msg_send![self, setRayMaskOptions: options] }
|
||||
}
|
||||
|
||||
pub fn set_ray_stride(&self, stride: NSUInteger) {
|
||||
unsafe { msg_send![self, setRayStride: stride] }
|
||||
}
|
||||
|
||||
pub fn set_triangle_intersection_test_type(&self, test_type: MPSTriangleIntersectionTestType) {
|
||||
unsafe { msg_send![self, setTriangleIntersectionTestType: test_type] }
|
||||
}
|
||||
|
||||
pub fn encode_intersection_to_command_buffer(
|
||||
&self,
|
||||
command_buffer: &CommandBufferRef,
|
||||
intersection_type: MPSIntersectionType,
|
||||
ray_buffer: &BufferRef,
|
||||
ray_buffer_offset: NSUInteger,
|
||||
intersection_buffer: &BufferRef,
|
||||
intersection_buffer_offset: NSUInteger,
|
||||
ray_count: NSUInteger,
|
||||
acceleration_structure: &AccelerationStructureRef,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
encodeIntersectionToCommandBuffer: command_buffer
|
||||
intersectionType: intersection_type
|
||||
rayBuffer: ray_buffer
|
||||
rayBufferOffset: ray_buffer_offset
|
||||
intersectionBuffer: intersection_buffer
|
||||
intersectionBufferOffset: intersection_buffer_offset
|
||||
rayCount: ray_count
|
||||
accelerationStructure: acceleration_structure
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recommended_minimum_ray_batch_size_for_ray_count(
|
||||
&self,
|
||||
ray_count: NSUInteger,
|
||||
) -> NSUInteger {
|
||||
unsafe { msg_send![self, recommendedMinimumRayBatchSizeForRayCount: ray_count] }
|
||||
}
|
||||
}
|
||||
|
||||
/// A group of acceleration structures which may be used together in an instance acceleration structure.
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsaccelerationstructuregroup>
|
||||
pub enum MPSAccelerationStructureGroup {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MPSAccelerationStructureGroup;
|
||||
pub struct AccelerationStructureGroup;
|
||||
}
|
||||
|
||||
impl AccelerationStructureGroup {
|
||||
pub fn new_with_device(device: &DeviceRef) -> Option<Self> {
|
||||
unsafe {
|
||||
let group: AccelerationStructureGroup =
|
||||
msg_send![class!(MPSAccelerationStructureGroup), alloc];
|
||||
let ptr: *mut Object = msg_send![group.as_ref(), initWithDevice: device];
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(group)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AccelerationStructureGroupRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
}
|
||||
|
||||
/// The base class for data structures that are built over geometry and used to accelerate ray tracing.
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsaccelerationstructure>
|
||||
pub enum MPSAccelerationStructure {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MPSAccelerationStructure;
|
||||
pub struct AccelerationStructure;
|
||||
}
|
||||
|
||||
impl AccelerationStructureRef {
|
||||
pub fn status(&self) -> MPSAccelerationStructureStatus {
|
||||
unsafe { msg_send![self, status] }
|
||||
}
|
||||
|
||||
pub fn usage(&self) -> MPSAccelerationStructureUsage {
|
||||
unsafe { msg_send![self, usage] }
|
||||
}
|
||||
|
||||
pub fn set_usage(&self, usage: MPSAccelerationStructureUsage) {
|
||||
unsafe { msg_send![self, setUsage: usage] }
|
||||
}
|
||||
|
||||
pub fn group(&self) -> &AccelerationStructureGroupRef {
|
||||
unsafe { msg_send![self, group] }
|
||||
}
|
||||
|
||||
pub fn encode_refit_to_command_buffer(&self, buffer: &CommandBufferRef) {
|
||||
unsafe { msg_send![self, encodeRefitToCommandBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn rebuild(&self) {
|
||||
unsafe { msg_send![self, rebuild] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpspolygonaccelerationstructure>
|
||||
pub enum MPSPolygonAccelerationStructure {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MPSPolygonAccelerationStructure;
|
||||
pub struct PolygonAccelerationStructure;
|
||||
type ParentType = AccelerationStructure;
|
||||
}
|
||||
|
||||
impl PolygonAccelerationStructureRef {
|
||||
pub fn set_index_buffer(&self, buffer: Option<&BufferRef>) {
|
||||
unsafe { msg_send![self, setIndexBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn set_index_buffer_offset(&self, offset: NSUInteger) {
|
||||
unsafe { msg_send![self, setIndexBufferOffset: offset] }
|
||||
}
|
||||
|
||||
pub fn set_index_type(&self, data_type: MPSDataType) {
|
||||
unsafe { msg_send![self, setIndexType: data_type] }
|
||||
}
|
||||
|
||||
pub fn set_mask_buffer(&self, buffer: Option<&BufferRef>) {
|
||||
unsafe { msg_send![self, setMaskBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn set_mask_buffer_offset(&self, offset: NSUInteger) {
|
||||
unsafe { msg_send![self, setMaskBufferOffset: offset] }
|
||||
}
|
||||
|
||||
pub fn set_vertex_buffer(&self, buffer: Option<&BufferRef>) {
|
||||
unsafe { msg_send![self, setVertexBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn set_vertex_buffer_offset(&self, offset: NSUInteger) {
|
||||
unsafe { msg_send![self, setVertexBufferOffset: offset] }
|
||||
}
|
||||
|
||||
pub fn set_vertex_stride(&self, stride: NSUInteger) {
|
||||
unsafe { msg_send![self, setVertexStride: stride] }
|
||||
}
|
||||
}
|
||||
|
||||
/// An acceleration structure built over triangles.
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpstriangleaccelerationstructure>
|
||||
pub enum MPSTriangleAccelerationStructure {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MPSTriangleAccelerationStructure;
|
||||
pub struct TriangleAccelerationStructure;
|
||||
type ParentType = PolygonAccelerationStructure;
|
||||
}
|
||||
|
||||
impl TriangleAccelerationStructure {
|
||||
pub fn from_device(device: &DeviceRef) -> Option<Self> {
|
||||
unsafe {
|
||||
let structure: TriangleAccelerationStructure =
|
||||
msg_send![class!(MPSTriangleAccelerationStructure), alloc];
|
||||
let ptr: *mut Object = msg_send![structure.as_ref(), initWithDevice: device];
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(structure)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TriangleAccelerationStructureRef {
|
||||
pub fn triangle_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, triangleCount] }
|
||||
}
|
||||
|
||||
pub fn set_triangle_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setTriangleCount: count] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpstransformtype>
|
||||
#[repr(u64)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum MPSTransformType {
|
||||
Float4x4 = 0,
|
||||
Identity = 1,
|
||||
}
|
||||
|
||||
/// An acceleration structure built over instances of other acceleration structures
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsinstanceaccelerationstructure>
|
||||
pub enum MPSInstanceAccelerationStructure {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MPSInstanceAccelerationStructure;
|
||||
pub struct InstanceAccelerationStructure;
|
||||
type ParentType = AccelerationStructure;
|
||||
}
|
||||
|
||||
impl InstanceAccelerationStructure {
|
||||
pub fn init_with_group(group: &AccelerationStructureGroupRef) -> Option<Self> {
|
||||
unsafe {
|
||||
let structure: InstanceAccelerationStructure =
|
||||
msg_send![class!(MPSInstanceAccelerationStructure), alloc];
|
||||
let ptr: *mut Object = msg_send![structure.as_ref(), initWithGroup: group];
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(structure)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InstanceAccelerationStructureRef {
|
||||
/// Marshal to Rust Vec
|
||||
pub fn acceleration_structures(&self) -> Vec<PolygonAccelerationStructure> {
|
||||
unsafe {
|
||||
let acs: *mut Object = msg_send![self, accelerationStructures];
|
||||
let count: NSUInteger = msg_send![acs, count];
|
||||
let ret = (0..count)
|
||||
.map(|i| {
|
||||
let ac = msg_send![acs, objectAtIndex: i];
|
||||
PolygonAccelerationStructure::from_ptr(ac)
|
||||
})
|
||||
.collect();
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// Marshal from Rust slice
|
||||
pub fn set_acceleration_structures(&self, acs: &[&PolygonAccelerationStructureRef]) {
|
||||
let ns_array = Array::<PolygonAccelerationStructure>::from_slice(acs);
|
||||
unsafe { msg_send![self, setAccelerationStructures: ns_array] }
|
||||
}
|
||||
|
||||
pub fn instance_buffer(&self) -> &BufferRef {
|
||||
unsafe { msg_send![self, instanceBuffer] }
|
||||
}
|
||||
|
||||
pub fn set_instance_buffer(&self, buffer: &BufferRef) {
|
||||
unsafe { msg_send![self, setInstanceBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn instance_buffer_offset(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, instanceBufferOffset] }
|
||||
}
|
||||
|
||||
pub fn set_instance_buffer_offset(&self, offset: NSUInteger) {
|
||||
unsafe { msg_send![self, setInstanceBufferOffset: offset] }
|
||||
}
|
||||
|
||||
pub fn transform_buffer(&self) -> &BufferRef {
|
||||
unsafe { msg_send![self, transformBuffer] }
|
||||
}
|
||||
|
||||
pub fn set_transform_buffer(&self, buffer: &BufferRef) {
|
||||
unsafe { msg_send![self, setTransformBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn transform_buffer_offset(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, transformBufferOffset] }
|
||||
}
|
||||
|
||||
pub fn set_transform_buffer_offset(&self, offset: NSUInteger) {
|
||||
unsafe { msg_send![self, setTransformBufferOffset: offset] }
|
||||
}
|
||||
|
||||
pub fn transform_type(&self) -> MPSTransformType {
|
||||
unsafe { msg_send![self, transformType] }
|
||||
}
|
||||
|
||||
pub fn set_transform_type(&self, transform_type: MPSTransformType) {
|
||||
unsafe { msg_send![self, setTransformType: transform_type] }
|
||||
}
|
||||
|
||||
pub fn mask_buffer(&self) -> &BufferRef {
|
||||
unsafe { msg_send![self, maskBuffer] }
|
||||
}
|
||||
|
||||
pub fn set_mask_buffer(&self, buffer: &BufferRef) {
|
||||
unsafe { msg_send![self, setMaskBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn mask_buffer_offset(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, maskBufferOffset] }
|
||||
}
|
||||
|
||||
pub fn set_mask_buffer_offset(&self, offset: NSUInteger) {
|
||||
unsafe { msg_send![self, setMaskBufferOffset: offset] }
|
||||
}
|
||||
|
||||
pub fn instance_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, instanceCount] }
|
||||
}
|
||||
|
||||
pub fn set_instance_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setInstanceCount: count] }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct MPSPackedFloat3 {
|
||||
pub elements: [f32; 3],
|
||||
}
|
||||
|
||||
/// Represents a 3D ray with an origin, a direction, and an intersection distance range from the origin.
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsrayoriginmindistancedirectionmaxdistance>
|
||||
#[repr(C)]
|
||||
pub struct MPSRayOriginMinDistanceDirectionMaxDistance {
|
||||
/// Ray origin. The intersection test will be skipped if the origin contains NaNs or infinities.
|
||||
pub origin: MPSPackedFloat3,
|
||||
/// Minimum intersection distance from the origin along the ray direction.
|
||||
/// The intersection test will be skipped if the minimum distance is equal to positive infinity or NaN.
|
||||
pub min_distance: f32,
|
||||
/// Ray direction. Does not need to be normalized. The intersection test will be skipped if
|
||||
/// the direction has length zero or contains NaNs or infinities.
|
||||
pub direction: MPSPackedFloat3,
|
||||
/// Maximum intersection distance from the origin along the ray direction. May be infinite.
|
||||
/// The intersection test will be skipped if the maximum distance is less than zero, NaN, or
|
||||
/// less than the minimum intersection distance.
|
||||
pub max_distance: f32,
|
||||
}
|
||||
|
||||
/// Intersection result which contains the distance from the ray origin to the intersection point,
|
||||
/// the index of the intersected primitive, and the first two barycentric coordinates of the intersection point.
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metalperformanceshaders/mpsintersectiondistanceprimitiveindexcoordinates>
|
||||
#[repr(C)]
|
||||
pub struct MPSIntersectionDistancePrimitiveIndexCoordinates {
|
||||
/// Distance from the ray origin to the intersection point along the ray direction vector such
|
||||
/// that `intersection = ray.origin + ray.direction * distance`.
|
||||
/// Is negative if there is no intersection. If the intersection type is `MPSIntersectionTypeAny`,
|
||||
/// is a positive value for a hit or a negative value for a miss.
|
||||
pub distance: f32,
|
||||
/// Index of the intersected primitive. Undefined if the ray does not intersect a primitive or
|
||||
/// if the intersection type is `MPSIntersectionTypeAny`.
|
||||
pub primitive_index: u32,
|
||||
/// The first two barycentric coordinates `U` and `V` of the intersection point.
|
||||
/// The third coordinate `W = 1 - U - V`. Undefined if the ray does not intersect a primitive or
|
||||
/// if the intersection type is `MPSIntersectionTypeAny`.
|
||||
pub coordinates: [f32; 2],
|
||||
}
|
||||
471
third-party/vendor/metal/src/pipeline/compute.rs
vendored
Normal file
471
third-party/vendor/metal/src/pipeline/compute.rs
vendored
Normal file
|
|
@ -0,0 +1,471 @@
|
|||
// Copyright 2017 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
|
||||
use objc::runtime::{NO, YES};
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlattributeformat>
|
||||
#[repr(u64)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum MTLAttributeFormat {
|
||||
Invalid = 0,
|
||||
UChar2 = 1,
|
||||
UChar3 = 2,
|
||||
UChar4 = 3,
|
||||
Char2 = 4,
|
||||
Char3 = 5,
|
||||
Char4 = 6,
|
||||
UChar2Normalized = 7,
|
||||
UChar3Normalized = 8,
|
||||
UChar4Normalized = 9,
|
||||
Char2Normalized = 10,
|
||||
Char3Normalized = 11,
|
||||
Char4Normalized = 12,
|
||||
UShort2 = 13,
|
||||
UShort3 = 14,
|
||||
UShort4 = 15,
|
||||
Short2 = 16,
|
||||
Short3 = 17,
|
||||
Short4 = 18,
|
||||
UShort2Normalized = 19,
|
||||
UShort3Normalized = 20,
|
||||
UShort4Normalized = 21,
|
||||
Short2Normalized = 22,
|
||||
Short3Normalized = 23,
|
||||
Short4Normalized = 24,
|
||||
Half2 = 25,
|
||||
Half3 = 26,
|
||||
Half4 = 27,
|
||||
Float = 28,
|
||||
Float2 = 29,
|
||||
Float3 = 30,
|
||||
Float4 = 31,
|
||||
Int = 32,
|
||||
Int2 = 33,
|
||||
Int3 = 34,
|
||||
Int4 = 35,
|
||||
UInt = 36,
|
||||
UInt2 = 37,
|
||||
UInt3 = 38,
|
||||
UInt4 = 39,
|
||||
Int1010102Normalized = 40,
|
||||
UInt1010102Normalized = 41,
|
||||
UChar4Normalized_BGRA = 42,
|
||||
UChar = 45,
|
||||
Char = 46,
|
||||
UCharNormalized = 47,
|
||||
CharNormalized = 48,
|
||||
UShort = 49,
|
||||
Short = 50,
|
||||
UShortNormalized = 51,
|
||||
ShortNormalized = 52,
|
||||
Half = 53,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlstepfunction>
|
||||
#[repr(u64)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum MTLStepFunction {
|
||||
Constant = 0,
|
||||
PerInstance = 1,
|
||||
PerPatch = 2,
|
||||
PerPatchControlPoint = 3,
|
||||
PerVertex = 4,
|
||||
ThreadPositionInGridX = 5,
|
||||
ThreadPositionInGridXIndexed = 6,
|
||||
ThreadPositionInGridY = 7,
|
||||
ThreadPositionInGridYIndexed = 8,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcomputepipelinedescriptor>
|
||||
pub enum MTLComputePipelineDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLComputePipelineDescriptor;
|
||||
pub struct ComputePipelineDescriptor;
|
||||
}
|
||||
|
||||
impl ComputePipelineDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLComputePipelineDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputePipelineDescriptorRef {
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_function(&self) -> Option<&FunctionRef> {
|
||||
unsafe { msg_send![self, computeFunction] }
|
||||
}
|
||||
|
||||
pub fn set_compute_function(&self, function: Option<&FunctionRef>) {
|
||||
unsafe { msg_send![self, setComputeFunction: function] }
|
||||
}
|
||||
|
||||
pub fn thread_group_size_is_multiple_of_thread_execution_width(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, threadGroupSizeIsMultipleOfThreadExecutionWidth] }
|
||||
}
|
||||
|
||||
pub fn set_thread_group_size_is_multiple_of_thread_execution_width(
|
||||
&self,
|
||||
size_is_multiple_of_width: bool,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
setThreadGroupSizeIsMultipleOfThreadExecutionWidth: size_is_multiple_of_width
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(macos(10.14), ios(12.0));
|
||||
pub fn max_total_threads_per_threadgroup(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, maxTotalThreadsPerThreadgroup] }
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(macos(10.14), ios(12.0));
|
||||
pub fn set_max_total_threads_per_threadgroup(&self, max_total_threads: NSUInteger) {
|
||||
unsafe { msg_send![self, setMaxTotalThreadsPerThreadgroup: max_total_threads] }
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(ios(13.0),macos(11.0));
|
||||
pub fn support_indirect_command_buffers(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, supportIndirectCommandBuffers] }
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(ios(13.0),macos(11.0));
|
||||
pub fn set_support_indirect_command_buffers(&self, support: bool) {
|
||||
unsafe { msg_send![self, setSupportIndirectCommandBuffers: support] }
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(macos(11.0), ios(14.0));
|
||||
pub fn support_adding_binary_functions(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, supportAddingBinaryFunctions] }
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(macos(11.0), ios(14.0));
|
||||
pub fn set_support_adding_binary_functions(&self, support: bool) {
|
||||
unsafe { msg_send![self, setSupportAddingBinaryFunctions: support] }
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(macos(11.0), ios(14.0));
|
||||
pub fn max_call_stack_depth(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, maxCallStackDepth] }
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(macos(11.0), ios(14.0));
|
||||
pub fn set_max_call_stack_depth(&self, depth: NSUInteger) {
|
||||
unsafe { msg_send![self, setMaxCallStackDepth: depth] }
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(macos(11.0), ios(14.0));
|
||||
/// Marshal to Rust Vec
|
||||
pub fn insert_libraries(&self) -> Vec<DynamicLibrary> {
|
||||
unsafe {
|
||||
let libraries: *mut Object = msg_send![self, insertLibraries];
|
||||
let count: NSUInteger = msg_send![libraries, count];
|
||||
let ret = (0..count)
|
||||
.map(|i| {
|
||||
let lib = msg_send![libraries, objectAtIndex: i];
|
||||
DynamicLibrary::from_ptr(lib)
|
||||
})
|
||||
.collect();
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// Marshal from Rust slice
|
||||
pub fn set_insert_libraries(&self, libraries: &[&DynamicLibraryRef]) {
|
||||
let ns_array = Array::<DynamicLibrary>::from_slice(libraries);
|
||||
unsafe { msg_send![self, setInsertLibraries: ns_array] }
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(macos(11.0), ios(14.0));
|
||||
/// Marshal to Rust Vec
|
||||
pub fn binary_archives(&self) -> Vec<BinaryArchive> {
|
||||
unsafe {
|
||||
let archives: *mut Object = msg_send![self, binaryArchives];
|
||||
let count: NSUInteger = msg_send![archives, count];
|
||||
let ret = (0..count)
|
||||
.map(|i| {
|
||||
let a = msg_send![archives, objectAtIndex: i];
|
||||
BinaryArchive::from_ptr(a)
|
||||
})
|
||||
.collect();
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(macos(11.0), ios(14.0));
|
||||
/// Marshal from Rust slice
|
||||
pub fn set_binary_archives(&self, archives: &[&BinaryArchiveRef]) {
|
||||
let ns_array = Array::<BinaryArchive>::from_slice(archives);
|
||||
unsafe { msg_send![self, setBinaryArchives: ns_array] }
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(macos(11.0), ios(14.0));
|
||||
pub fn linked_functions(&self) -> &LinkedFunctionsRef {
|
||||
unsafe { msg_send![self, linkedFunctions] }
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(macos(11.0), ios(14.0));
|
||||
pub fn set_linked_functions(&self, functions: &LinkedFunctionsRef) {
|
||||
unsafe { msg_send![self, setLinkedFunctions: functions] }
|
||||
}
|
||||
|
||||
pub fn stage_input_descriptor(&self) -> Option<&StageInputOutputDescriptorRef> {
|
||||
unsafe { msg_send![self, stageInputDescriptor] }
|
||||
}
|
||||
|
||||
pub fn set_stage_input_descriptor(&self, descriptor: Option<&StageInputOutputDescriptorRef>) {
|
||||
unsafe { msg_send![self, setStageInputDescriptor: descriptor] }
|
||||
}
|
||||
|
||||
pub fn buffers(&self) -> Option<&PipelineBufferDescriptorArrayRef> {
|
||||
unsafe { msg_send![self, buffers] }
|
||||
}
|
||||
|
||||
pub fn reset(&self) {
|
||||
unsafe { msg_send![self, reset] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcomputepipelinestate>
|
||||
pub enum MTLComputePipelineState {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLComputePipelineState;
|
||||
pub struct ComputePipelineState;
|
||||
}
|
||||
|
||||
impl ComputePipelineStateRef {
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max_total_threads_per_threadgroup(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, maxTotalThreadsPerThreadgroup] }
|
||||
}
|
||||
|
||||
pub fn thread_execution_width(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, threadExecutionWidth] }
|
||||
}
|
||||
|
||||
pub fn static_threadgroup_memory_length(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, staticThreadgroupMemoryLength] }
|
||||
}
|
||||
|
||||
/// Only available on (ios(11.0), macos(11.0), macCatalyst(14.0)) NOT available on (tvos)
|
||||
pub fn imageblock_memory_length_for_dimensions(&self, dimensions: MTLSize) -> NSUInteger {
|
||||
unsafe { msg_send![self, imageblockMemoryLengthForDimensions: dimensions] }
|
||||
}
|
||||
|
||||
/// Only available on (ios(13.0), macos(11.0))
|
||||
pub fn support_indirect_command_buffers(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, supportIndirectCommandBuffers] }
|
||||
}
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
pub fn function_handle_with_function(
|
||||
&self,
|
||||
function: &FunctionRef,
|
||||
) -> Option<&FunctionHandleRef> {
|
||||
unsafe { msg_send![self, functionHandleWithFunction: function] }
|
||||
}
|
||||
|
||||
// API_AVAILABLE(macos(11.0), ios(14.0));
|
||||
// TODO: newComputePipelineStateWithAdditionalBinaryFunctions
|
||||
// - (nullable id <MTLComputePipelineState>)newComputePipelineStateWithAdditionalBinaryFunctions:(nonnull NSArray<id<MTLFunction>> *)functions error:(__autoreleasing NSError **)error
|
||||
|
||||
// API_AVAILABLE(macos(11.0), ios(14.0));
|
||||
// TODO: newVisibleFunctionTableWithDescriptor
|
||||
// - (nullable id<MTLVisibleFunctionTable>)newVisibleFunctionTableWithDescriptor:(MTLVisibleFunctionTableDescriptor * __nonnull)descriptor
|
||||
|
||||
/// Only available on (macos(11.0), ios(14.0))
|
||||
pub fn new_intersection_function_table_with_descriptor(
|
||||
&self,
|
||||
descriptor: &IntersectionFunctionTableDescriptorRef,
|
||||
) -> IntersectionFunctionTable {
|
||||
unsafe { msg_send![self, newIntersectionFunctionTableWithDescriptor: descriptor] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlstageinputoutputdescriptor>
|
||||
pub enum MTLStageInputOutputDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLStageInputOutputDescriptor;
|
||||
pub struct StageInputOutputDescriptor;
|
||||
}
|
||||
|
||||
impl StageInputOutputDescriptor {
|
||||
pub fn new<'a>() -> &'a StageInputOutputDescriptorRef {
|
||||
unsafe {
|
||||
let class = class!(MTLStageInputOutputDescriptor);
|
||||
msg_send![class, stageInputOutputDescriptor]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StageInputOutputDescriptorRef {
|
||||
pub fn attributes(&self) -> Option<&AttributeDescriptorArrayRef> {
|
||||
unsafe { msg_send![self, attributes] }
|
||||
}
|
||||
|
||||
pub fn index_buffer_index(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, indexBufferIndex] }
|
||||
}
|
||||
|
||||
pub fn set_index_buffer_index(&self, idx_buffer_idx: NSUInteger) {
|
||||
unsafe { msg_send![self, setIndexBufferIndex: idx_buffer_idx] }
|
||||
}
|
||||
|
||||
pub fn index_type(&self) -> MTLIndexType {
|
||||
unsafe { msg_send![self, indexType] }
|
||||
}
|
||||
|
||||
pub fn set_index_type(&self, index_ty: MTLIndexType) {
|
||||
unsafe { msg_send![self, setIndexType: index_ty] }
|
||||
}
|
||||
|
||||
pub fn layouts(&self) -> Option<&BufferLayoutDescriptorArrayRef> {
|
||||
unsafe { msg_send![self, layouts] }
|
||||
}
|
||||
|
||||
pub fn reset(&self) {
|
||||
unsafe { msg_send![self, reset] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlattributedescriptorarray>
|
||||
pub enum MTLAttributeDescriptorArray {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLAttributeDescriptorArray;
|
||||
pub struct AttributeDescriptorArray;
|
||||
}
|
||||
|
||||
impl AttributeDescriptorArrayRef {
|
||||
pub fn object_at(&self, index: NSUInteger) -> Option<&AttributeDescriptorRef> {
|
||||
unsafe { msg_send![self, objectAtIndexedSubscript: index] }
|
||||
}
|
||||
|
||||
pub fn set_object_at(&self, index: NSUInteger, buffer_desc: Option<&AttributeDescriptorRef>) {
|
||||
unsafe { msg_send![self, setObject:buffer_desc atIndexedSubscript:index] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlattributedescriptor>
|
||||
pub enum MTLAttributeDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLAttributeDescriptor;
|
||||
pub struct AttributeDescriptor;
|
||||
}
|
||||
|
||||
impl AttributeDescriptorRef {
|
||||
pub fn buffer_index(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, bufferIndex] }
|
||||
}
|
||||
|
||||
pub fn set_buffer_index(&self, buffer_index: NSUInteger) {
|
||||
unsafe { msg_send![self, setBufferIndex: buffer_index] }
|
||||
}
|
||||
|
||||
pub fn format(&self) -> MTLAttributeFormat {
|
||||
unsafe { msg_send![self, format] }
|
||||
}
|
||||
|
||||
pub fn set_format(&self, format: MTLAttributeFormat) {
|
||||
unsafe { msg_send![self, setFormat: format] }
|
||||
}
|
||||
|
||||
pub fn offset(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, offset] }
|
||||
}
|
||||
|
||||
pub fn set_offset(&self, offset: NSUInteger) {
|
||||
unsafe { msg_send![self, setOffset: offset] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlbufferlayoutdescriptorarray>
|
||||
pub enum MTLBufferLayoutDescriptorArray {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLBufferLayoutDescriptorArray;
|
||||
pub struct BufferLayoutDescriptorArray;
|
||||
}
|
||||
|
||||
impl BufferLayoutDescriptorArrayRef {
|
||||
pub fn object_at(&self, index: NSUInteger) -> Option<&BufferLayoutDescriptorRef> {
|
||||
unsafe { msg_send![self, objectAtIndexedSubscript: index] }
|
||||
}
|
||||
|
||||
pub fn set_object_at(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
buffer_desc: Option<&BufferLayoutDescriptorRef>,
|
||||
) {
|
||||
unsafe { msg_send![self, setObject:buffer_desc atIndexedSubscript:index] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlbufferlayoutdescriptor>
|
||||
pub enum MTLBufferLayoutDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLBufferLayoutDescriptor;
|
||||
pub struct BufferLayoutDescriptor;
|
||||
}
|
||||
|
||||
impl BufferLayoutDescriptorRef {
|
||||
pub fn step_function(&self) -> MTLStepFunction {
|
||||
unsafe { msg_send![self, stepFunction] }
|
||||
}
|
||||
|
||||
pub fn set_step_function(&self, step_function: MTLStepFunction) {
|
||||
unsafe { msg_send![self, setStepFunction: step_function] }
|
||||
}
|
||||
|
||||
pub fn step_rate(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, stepRate] }
|
||||
}
|
||||
|
||||
pub fn set_step_rate(&self, step_rate: NSUInteger) {
|
||||
unsafe { msg_send![self, setStepRate: step_rate] }
|
||||
}
|
||||
|
||||
pub fn stride(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, stride] }
|
||||
}
|
||||
|
||||
pub fn set_stride(&self, stride: NSUInteger) {
|
||||
unsafe { msg_send![self, setStride: stride] }
|
||||
}
|
||||
}
|
||||
71
third-party/vendor/metal/src/pipeline/mod.rs
vendored
Normal file
71
third-party/vendor/metal/src/pipeline/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright 2017 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
|
||||
mod compute;
|
||||
mod render;
|
||||
|
||||
pub use self::compute::*;
|
||||
pub use self::render::*;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlmutability>
|
||||
#[repr(u64)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum MTLMutability {
|
||||
Default = 0,
|
||||
Mutable = 1,
|
||||
Immutable = 2,
|
||||
}
|
||||
|
||||
impl Default for MTLMutability {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
MTLMutability::Default
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlpipelinebufferdescriptorarray>
|
||||
pub enum MTLPipelineBufferDescriptorArray {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLPipelineBufferDescriptorArray;
|
||||
pub struct PipelineBufferDescriptorArray;
|
||||
}
|
||||
|
||||
impl PipelineBufferDescriptorArrayRef {
|
||||
pub fn object_at(&self, index: NSUInteger) -> Option<&PipelineBufferDescriptorRef> {
|
||||
unsafe { msg_send![self, objectAtIndexedSubscript: index] }
|
||||
}
|
||||
|
||||
pub fn set_object_at(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
buffer_desc: Option<&PipelineBufferDescriptorRef>,
|
||||
) {
|
||||
unsafe { msg_send![self, setObject:buffer_desc atIndexedSubscript:index] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlpipelinebufferdescriptor>
|
||||
pub enum MTLPipelineBufferDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLPipelineBufferDescriptor;
|
||||
pub struct PipelineBufferDescriptor;
|
||||
}
|
||||
|
||||
impl PipelineBufferDescriptorRef {
|
||||
pub fn mutability(&self) -> MTLMutability {
|
||||
unsafe { msg_send![self, mutability] }
|
||||
}
|
||||
|
||||
pub fn set_mutability(&self, new_mutability: MTLMutability) {
|
||||
unsafe { msg_send![self, setMutability: new_mutability] }
|
||||
}
|
||||
}
|
||||
719
third-party/vendor/metal/src/pipeline/render.rs
vendored
Normal file
719
third-party/vendor/metal/src/pipeline/render.rs
vendored
Normal file
|
|
@ -0,0 +1,719 @@
|
|||
// Copyright 2017 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
|
||||
use objc::runtime::{NO, YES};
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlblendfactor>
|
||||
#[repr(u64)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum MTLBlendFactor {
|
||||
Zero = 0,
|
||||
One = 1,
|
||||
SourceColor = 2,
|
||||
OneMinusSourceColor = 3,
|
||||
SourceAlpha = 4,
|
||||
OneMinusSourceAlpha = 5,
|
||||
DestinationColor = 6,
|
||||
OneMinusDestinationColor = 7,
|
||||
DestinationAlpha = 8,
|
||||
OneMinusDestinationAlpha = 9,
|
||||
SourceAlphaSaturated = 10,
|
||||
BlendColor = 11,
|
||||
OneMinusBlendColor = 12,
|
||||
BlendAlpha = 13,
|
||||
OneMinusBlendAlpha = 14,
|
||||
Source1Color = 15,
|
||||
OneMinusSource1Color = 16,
|
||||
Source1Alpha = 17,
|
||||
OneMinusSource1Alpha = 18,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlblendoperation>
|
||||
#[repr(u64)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum MTLBlendOperation {
|
||||
Add = 0,
|
||||
Subtract = 1,
|
||||
ReverseSubtract = 2,
|
||||
Min = 3,
|
||||
Max = 4,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcolorwritemask>
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct MTLColorWriteMask: NSUInteger {
|
||||
const None = 0;
|
||||
const Red = 0x1 << 3;
|
||||
const Green = 0x1 << 2;
|
||||
const Blue = 0x1 << 1;
|
||||
const Alpha = 0x1 << 0;
|
||||
const All = 0xf;
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlprimitivetopologyclass>
|
||||
#[repr(u64)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum MTLPrimitiveTopologyClass {
|
||||
Unspecified = 0,
|
||||
Point = 1,
|
||||
Line = 2,
|
||||
Triangle = 3,
|
||||
}
|
||||
|
||||
// TODO: MTLTessellationPartitionMode
|
||||
// TODO: MTLTessellationFactorStepFunction
|
||||
// TODO: MTLTessellationFactorFormat
|
||||
// TODO: MTLTessellationControlPointIndexType
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderpipelinecolorattachmentdescriptor>
|
||||
pub enum MTLRenderPipelineColorAttachmentDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLRenderPipelineColorAttachmentDescriptor;
|
||||
pub struct RenderPipelineColorAttachmentDescriptor;
|
||||
}
|
||||
|
||||
impl RenderPipelineColorAttachmentDescriptorRef {
|
||||
pub fn pixel_format(&self) -> MTLPixelFormat {
|
||||
unsafe { msg_send![self, pixelFormat] }
|
||||
}
|
||||
|
||||
pub fn set_pixel_format(&self, pixel_format: MTLPixelFormat) {
|
||||
unsafe { msg_send![self, setPixelFormat: pixel_format] }
|
||||
}
|
||||
|
||||
pub fn is_blending_enabled(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isBlendingEnabled] }
|
||||
}
|
||||
|
||||
pub fn set_blending_enabled(&self, enabled: bool) {
|
||||
unsafe { msg_send![self, setBlendingEnabled: enabled] }
|
||||
}
|
||||
|
||||
pub fn source_rgb_blend_factor(&self) -> MTLBlendFactor {
|
||||
unsafe { msg_send![self, sourceRGBBlendFactor] }
|
||||
}
|
||||
|
||||
pub fn set_source_rgb_blend_factor(&self, blend_factor: MTLBlendFactor) {
|
||||
unsafe { msg_send![self, setSourceRGBBlendFactor: blend_factor] }
|
||||
}
|
||||
|
||||
pub fn destination_rgb_blend_factor(&self) -> MTLBlendFactor {
|
||||
unsafe { msg_send![self, destinationRGBBlendFactor] }
|
||||
}
|
||||
|
||||
pub fn set_destination_rgb_blend_factor(&self, blend_factor: MTLBlendFactor) {
|
||||
unsafe { msg_send![self, setDestinationRGBBlendFactor: blend_factor] }
|
||||
}
|
||||
|
||||
pub fn rgb_blend_operation(&self) -> MTLBlendOperation {
|
||||
unsafe { msg_send![self, rgbBlendOperation] }
|
||||
}
|
||||
|
||||
pub fn set_rgb_blend_operation(&self, blend_operation: MTLBlendOperation) {
|
||||
unsafe { msg_send![self, setRgbBlendOperation: blend_operation] }
|
||||
}
|
||||
|
||||
pub fn source_alpha_blend_factor(&self) -> MTLBlendFactor {
|
||||
unsafe { msg_send![self, sourceAlphaBlendFactor] }
|
||||
}
|
||||
|
||||
pub fn set_source_alpha_blend_factor(&self, blend_factor: MTLBlendFactor) {
|
||||
unsafe { msg_send![self, setSourceAlphaBlendFactor: blend_factor] }
|
||||
}
|
||||
|
||||
pub fn destination_alpha_blend_factor(&self) -> MTLBlendFactor {
|
||||
unsafe { msg_send![self, destinationAlphaBlendFactor] }
|
||||
}
|
||||
|
||||
pub fn set_destination_alpha_blend_factor(&self, blend_factor: MTLBlendFactor) {
|
||||
unsafe { msg_send![self, setDestinationAlphaBlendFactor: blend_factor] }
|
||||
}
|
||||
|
||||
pub fn alpha_blend_operation(&self) -> MTLBlendOperation {
|
||||
unsafe { msg_send![self, alphaBlendOperation] }
|
||||
}
|
||||
|
||||
pub fn set_alpha_blend_operation(&self, blend_operation: MTLBlendOperation) {
|
||||
unsafe { msg_send![self, setAlphaBlendOperation: blend_operation] }
|
||||
}
|
||||
|
||||
pub fn write_mask(&self) -> MTLColorWriteMask {
|
||||
unsafe { msg_send![self, writeMask] }
|
||||
}
|
||||
|
||||
pub fn set_write_mask(&self, mask: MTLColorWriteMask) {
|
||||
unsafe { msg_send![self, setWriteMask: mask] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderpipelinereflection>
|
||||
pub enum MTLRenderPipelineReflection {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLRenderPipelineReflection;
|
||||
pub struct RenderPipelineReflection;
|
||||
}
|
||||
|
||||
impl RenderPipelineReflection {
|
||||
#[cfg(feature = "private")]
|
||||
pub unsafe fn new(
|
||||
vertex_data: *mut std::ffi::c_void,
|
||||
fragment_data: *mut std::ffi::c_void,
|
||||
vertex_desc: *mut std::ffi::c_void,
|
||||
device: &DeviceRef,
|
||||
options: u64,
|
||||
flags: u64,
|
||||
) -> Self {
|
||||
let class = class!(MTLRenderPipelineReflection);
|
||||
let this: RenderPipelineReflection = msg_send![class, alloc];
|
||||
let this_alias: *mut Object = msg_send![this.as_ref(), initWithVertexData:vertex_data
|
||||
fragmentData:fragment_data
|
||||
serializedVertexDescriptor:vertex_desc
|
||||
device:device
|
||||
options:options
|
||||
flags:flags];
|
||||
if this_alias.is_null() {
|
||||
panic!("[MTLRenderPipelineReflection init] failed");
|
||||
}
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderPipelineReflectionRef {
|
||||
/// An array of objects that describe the arguments of a fragment function.
|
||||
pub fn fragment_arguments(&self) -> &ArgumentArrayRef {
|
||||
unsafe { msg_send![self, fragmentArguments] }
|
||||
}
|
||||
|
||||
/// An array of objects that describe the arguments of a vertex function.
|
||||
pub fn vertex_arguments(&self) -> &ArgumentArrayRef {
|
||||
unsafe { msg_send![self, vertexArguments] }
|
||||
}
|
||||
|
||||
/// An array of objects that describe the arguments of a tile shading function.
|
||||
pub fn tile_arguments(&self) -> &ArgumentArrayRef {
|
||||
unsafe { msg_send![self, tileArguments] }
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: Find documentation link.
|
||||
pub enum MTLArgumentArray {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLArgumentArray;
|
||||
pub struct ArgumentArray;
|
||||
}
|
||||
|
||||
impl ArgumentArrayRef {
|
||||
pub fn object_at(&self, index: NSUInteger) -> Option<&ArgumentRef> {
|
||||
unsafe { msg_send![self, objectAtIndexedSubscript: index] }
|
||||
}
|
||||
|
||||
pub fn count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, count] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcomputepipelinereflection>
|
||||
pub enum MTLComputePipelineReflection {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLComputePipelineReflection;
|
||||
pub struct ComputePipelineReflection;
|
||||
}
|
||||
|
||||
impl ComputePipelineReflectionRef {
|
||||
/// An array of objects that describe the arguments of a compute function.
|
||||
pub fn arguments(&self) -> &ArgumentArrayRef {
|
||||
unsafe { msg_send![self, arguments] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlmeshrenderpipelinedescriptor>
|
||||
/// Only available in (macos(13.0), ios(16.0))
|
||||
pub enum MTLMeshRenderPipelineDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLMeshRenderPipelineDescriptor;
|
||||
pub struct MeshRenderPipelineDescriptor;
|
||||
}
|
||||
|
||||
impl MeshRenderPipelineDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLMeshRenderPipelineDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MeshRenderPipelineDescriptorRef {
|
||||
pub fn color_attachments(&self) -> &RenderPipelineColorAttachmentDescriptorArrayRef {
|
||||
unsafe { msg_send![self, colorAttachments] }
|
||||
}
|
||||
|
||||
pub fn depth_attachment_pixel_format(&self) -> MTLPixelFormat {
|
||||
unsafe { msg_send![self, depthAttachmentPixelFormat] }
|
||||
}
|
||||
|
||||
pub fn set_depth_attachment_pixel_format(&self, pixel_format: MTLPixelFormat) {
|
||||
unsafe { msg_send![self, setDepthAttachmentPixelFormat: pixel_format] }
|
||||
}
|
||||
|
||||
pub fn fragment_buffers(&self) -> Option<&PipelineBufferDescriptorArrayRef> {
|
||||
unsafe { msg_send![self, fragmentBuffers] }
|
||||
}
|
||||
|
||||
pub fn fragment_function(&self) -> Option<&FunctionRef> {
|
||||
unsafe { msg_send![self, fragmentFunction] }
|
||||
}
|
||||
|
||||
pub fn set_fragment_function(&self, function: Option<&FunctionRef>) {
|
||||
unsafe { msg_send![self, setFragmentFunction: function] }
|
||||
}
|
||||
|
||||
pub fn is_alpha_to_coverage_enabled(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isAlphaToCoverageEnabled] }
|
||||
}
|
||||
|
||||
pub fn set_alpha_to_coverage_enabled(&self, enabled: bool) {
|
||||
unsafe { msg_send![self, setAlphaToCoverageEnabled: enabled] }
|
||||
}
|
||||
|
||||
pub fn is_alpha_to_one_enabled(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isAlphaToOneEnabled] }
|
||||
}
|
||||
|
||||
pub fn set_alpha_to_one_enabled(&self, enabled: bool) {
|
||||
unsafe { msg_send![self, setAlphaToOneEnabled: enabled] }
|
||||
}
|
||||
|
||||
pub fn is_rasterization_enabled(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isRasterizationEnabled] }
|
||||
}
|
||||
|
||||
pub fn set_rasterization_enabled(&self, enabled: bool) {
|
||||
unsafe { msg_send![self, setRasterizationEnabled: enabled] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max_total_threadgroups_per_mesh_grid(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, maxTotalThreadgroupsPerMeshGrid] }
|
||||
}
|
||||
|
||||
pub fn set_max_total_threadgroups_per_mesh_grid(
|
||||
&self,
|
||||
max_total_threadgroups_per_mesh_grid: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
setMaxTotalThreadgroupsPerMeshGrid: max_total_threadgroups_per_mesh_grid
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max_total_threads_per_mesh_threadgroup(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, maxTotalThreadsPerMeshThreadgroup] }
|
||||
}
|
||||
|
||||
pub fn set_max_total_threads_per_mesh_threadgroup(
|
||||
&self,
|
||||
max_total_threads_per_mesh_threadgroup: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
setMaxTotalThreadsPerMeshThreadgroup: max_total_threads_per_mesh_threadgroup
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max_total_threads_per_object_threadgroup(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, maxTotalThreadsPerObjectThreadgroup] }
|
||||
}
|
||||
|
||||
pub fn set_max_total_threads_per_object_threadgroup(
|
||||
&self,
|
||||
max_total_threads_per_object_threadgroup: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
setMaxTotalThreadsPerObjectThreadgroup: max_total_threads_per_object_threadgroup
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max_vertex_amplification_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, maxVertexAmplificationCount] }
|
||||
}
|
||||
|
||||
pub fn set_max_vertex_amplification_count(&self, max_vertex_amplification_count: NSUInteger) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
setMaxVertexAmplificationCount: max_vertex_amplification_count
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mesh_buffers(&self) -> Option<&PipelineBufferDescriptorArrayRef> {
|
||||
unsafe { msg_send![self, meshBuffers] }
|
||||
}
|
||||
|
||||
pub fn mesh_function(&self) -> Option<&FunctionRef> {
|
||||
unsafe { msg_send![self, meshFunction] }
|
||||
}
|
||||
|
||||
pub fn set_mesh_function(&self, function: Option<&FunctionRef>) {
|
||||
unsafe { msg_send![self, setMeshFunction: function] }
|
||||
}
|
||||
|
||||
pub fn mesh_threadgroup_size_is_multiple_of_thread_execution_width(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth] }
|
||||
}
|
||||
|
||||
pub fn set_mesh_threadgroup_size_is_multiple_of_thread_execution_width(
|
||||
&self,
|
||||
mesh_threadgroup_size_is_multiple_of_thread_execution_width: bool,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth:
|
||||
mesh_threadgroup_size_is_multiple_of_thread_execution_width
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn object_buffers(&self) -> Option<&PipelineBufferDescriptorArrayRef> {
|
||||
unsafe { msg_send![self, objectBuffers] }
|
||||
}
|
||||
|
||||
pub fn object_function(&self) -> Option<&FunctionRef> {
|
||||
unsafe { msg_send![self, objectFunction] }
|
||||
}
|
||||
|
||||
pub fn set_object_function(&self, function: Option<&FunctionRef>) {
|
||||
unsafe { msg_send![self, setObjectFunction: function] }
|
||||
}
|
||||
|
||||
pub fn object_threadgroup_size_is_multiple_of_thread_execution_width(&self) -> bool {
|
||||
unsafe {
|
||||
msg_send_bool![
|
||||
self,
|
||||
isObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_object_threadgroup_size_is_multiple_of_thread_execution_width(
|
||||
&self,
|
||||
object_threadgroup_size_is_multiple_of_thread_execution_width: bool,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth:
|
||||
object_threadgroup_size_is_multiple_of_thread_execution_width
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn payload_memory_length(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, payloadMemoryLength] }
|
||||
}
|
||||
|
||||
pub fn set_payload_memory_length(&self, payload_memory_length: NSUInteger) {
|
||||
unsafe { msg_send![self, setPayloadMemoryLength: payload_memory_length] }
|
||||
}
|
||||
|
||||
pub fn raster_sample_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, rasterSampleCount] }
|
||||
}
|
||||
|
||||
pub fn set_raster_sample_count(&self, raster_sample_count: NSUInteger) {
|
||||
unsafe { msg_send![self, setRasterSampleCount: raster_sample_count] }
|
||||
}
|
||||
|
||||
pub fn stencil_attachment_pixel_format(&self) -> MTLPixelFormat {
|
||||
unsafe { msg_send![self, stencilAttachmentPixelFormat] }
|
||||
}
|
||||
|
||||
pub fn set_stencil_attachment_pixel_format(&self, pixel_format: MTLPixelFormat) {
|
||||
unsafe { msg_send![self, setStencilAttachmentPixelFormat: pixel_format] }
|
||||
}
|
||||
|
||||
pub fn reset(&self) {
|
||||
unsafe { msg_send![self, reset] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderpipelinedescriptor>
|
||||
pub enum MTLRenderPipelineDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLRenderPipelineDescriptor;
|
||||
pub struct RenderPipelineDescriptor;
|
||||
}
|
||||
|
||||
impl RenderPipelineDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLRenderPipelineDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderPipelineDescriptorRef {
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vertex_function(&self) -> Option<&FunctionRef> {
|
||||
unsafe { msg_send![self, vertexFunction] }
|
||||
}
|
||||
|
||||
pub fn set_vertex_function(&self, function: Option<&FunctionRef>) {
|
||||
unsafe { msg_send![self, setVertexFunction: function] }
|
||||
}
|
||||
|
||||
pub fn fragment_function(&self) -> Option<&FunctionRef> {
|
||||
unsafe { msg_send![self, fragmentFunction] }
|
||||
}
|
||||
|
||||
pub fn set_fragment_function(&self, function: Option<&FunctionRef>) {
|
||||
unsafe { msg_send![self, setFragmentFunction: function] }
|
||||
}
|
||||
|
||||
pub fn vertex_descriptor(&self) -> Option<&VertexDescriptorRef> {
|
||||
unsafe { msg_send![self, vertexDescriptor] }
|
||||
}
|
||||
|
||||
pub fn set_vertex_descriptor(&self, descriptor: Option<&VertexDescriptorRef>) {
|
||||
unsafe { msg_send![self, setVertexDescriptor: descriptor] }
|
||||
}
|
||||
|
||||
/// DEPRECATED - aliases rasterSampleCount property
|
||||
pub fn sample_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, sampleCount] }
|
||||
}
|
||||
|
||||
/// DEPRECATED - aliases rasterSampleCount property
|
||||
pub fn set_sample_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setSampleCount: count] }
|
||||
}
|
||||
|
||||
pub fn raster_sample_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, rasterSampleCount] }
|
||||
}
|
||||
|
||||
pub fn set_raster_sample_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setRasterSampleCount: count] }
|
||||
}
|
||||
|
||||
pub fn max_vertex_amplification_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, maxVertexAmplificationCount] }
|
||||
}
|
||||
|
||||
pub fn set_max_vertex_amplification_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setMaxVertexAmplificationCount: count] }
|
||||
}
|
||||
|
||||
pub fn is_alpha_to_coverage_enabled(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isAlphaToCoverageEnabled] }
|
||||
}
|
||||
|
||||
pub fn set_alpha_to_coverage_enabled(&self, enabled: bool) {
|
||||
unsafe { msg_send![self, setAlphaToCoverageEnabled: enabled] }
|
||||
}
|
||||
|
||||
pub fn is_alpha_to_one_enabled(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isAlphaToOneEnabled] }
|
||||
}
|
||||
|
||||
pub fn set_alpha_to_one_enabled(&self, enabled: bool) {
|
||||
unsafe { msg_send![self, setAlphaToOneEnabled: enabled] }
|
||||
}
|
||||
|
||||
pub fn is_rasterization_enabled(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isRasterizationEnabled] }
|
||||
}
|
||||
|
||||
pub fn set_rasterization_enabled(&self, enabled: bool) {
|
||||
unsafe { msg_send![self, setRasterizationEnabled: enabled] }
|
||||
}
|
||||
|
||||
pub fn color_attachments(&self) -> &RenderPipelineColorAttachmentDescriptorArrayRef {
|
||||
unsafe { msg_send![self, colorAttachments] }
|
||||
}
|
||||
|
||||
pub fn depth_attachment_pixel_format(&self) -> MTLPixelFormat {
|
||||
unsafe { msg_send![self, depthAttachmentPixelFormat] }
|
||||
}
|
||||
|
||||
pub fn set_depth_attachment_pixel_format(&self, pixel_format: MTLPixelFormat) {
|
||||
unsafe { msg_send![self, setDepthAttachmentPixelFormat: pixel_format] }
|
||||
}
|
||||
|
||||
pub fn stencil_attachment_pixel_format(&self) -> MTLPixelFormat {
|
||||
unsafe { msg_send![self, stencilAttachmentPixelFormat] }
|
||||
}
|
||||
|
||||
pub fn set_stencil_attachment_pixel_format(&self, pixel_format: MTLPixelFormat) {
|
||||
unsafe { msg_send![self, setStencilAttachmentPixelFormat: pixel_format] }
|
||||
}
|
||||
|
||||
pub fn input_primitive_topology(&self) -> MTLPrimitiveTopologyClass {
|
||||
unsafe { msg_send![self, inputPrimitiveTopology] }
|
||||
}
|
||||
|
||||
pub fn set_input_primitive_topology(&self, topology: MTLPrimitiveTopologyClass) {
|
||||
unsafe { msg_send![self, setInputPrimitiveTopology: topology] }
|
||||
}
|
||||
|
||||
#[cfg(feature = "private")]
|
||||
pub unsafe fn serialize_vertex_data(&self) -> *mut std::ffi::c_void {
|
||||
use std::ptr;
|
||||
let flags = 0;
|
||||
let err: *mut Object = ptr::null_mut();
|
||||
msg_send![self, newSerializedVertexDataWithFlags:flags
|
||||
error:err]
|
||||
}
|
||||
|
||||
#[cfg(feature = "private")]
|
||||
pub unsafe fn serialize_fragment_data(&self) -> *mut std::ffi::c_void {
|
||||
msg_send![self, serializeFragmentData]
|
||||
}
|
||||
|
||||
pub fn support_indirect_command_buffers(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, supportIndirectCommandBuffers] }
|
||||
}
|
||||
|
||||
pub fn set_support_indirect_command_buffers(&self, support: bool) {
|
||||
unsafe { msg_send![self, setSupportIndirectCommandBuffers: support] }
|
||||
}
|
||||
|
||||
pub fn vertex_buffers(&self) -> Option<&PipelineBufferDescriptorArrayRef> {
|
||||
unsafe { msg_send![self, vertexBuffers] }
|
||||
}
|
||||
|
||||
pub fn fragment_buffers(&self) -> Option<&PipelineBufferDescriptorArrayRef> {
|
||||
unsafe { msg_send![self, fragmentBuffers] }
|
||||
}
|
||||
|
||||
// TODO: tesselation stuff
|
||||
|
||||
/// API_AVAILABLE(macos(11.0), ios(14.0));
|
||||
/// Marshal to Rust Vec
|
||||
pub fn binary_archives(&self) -> Vec<BinaryArchive> {
|
||||
unsafe {
|
||||
let archives: *mut Object = msg_send![self, binaryArchives];
|
||||
let count: NSUInteger = msg_send![archives, count];
|
||||
let ret = (0..count)
|
||||
.map(|i| {
|
||||
let a = msg_send![archives, objectAtIndex: i];
|
||||
BinaryArchive::from_ptr(a)
|
||||
})
|
||||
.collect();
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// API_AVAILABLE(macos(11.0), ios(14.0));
|
||||
/// Marshal from Rust slice
|
||||
pub fn set_binary_archives(&self, archives: &[&BinaryArchiveRef]) {
|
||||
let ns_array = Array::<BinaryArchive>::from_slice(archives);
|
||||
unsafe { msg_send![self, setBinaryArchives: ns_array] }
|
||||
}
|
||||
|
||||
pub fn reset(&self) {
|
||||
unsafe { msg_send![self, reset] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderpipelinestate>
|
||||
pub enum MTLRenderPipelineState {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLRenderPipelineState;
|
||||
pub struct RenderPipelineState;
|
||||
}
|
||||
|
||||
impl RenderPipelineStateRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderpipelinecolorattachmentdescriptorarray>
|
||||
pub enum MTLRenderPipelineColorAttachmentDescriptorArray {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLRenderPipelineColorAttachmentDescriptorArray;
|
||||
pub struct RenderPipelineColorAttachmentDescriptorArray;
|
||||
}
|
||||
|
||||
impl RenderPipelineColorAttachmentDescriptorArrayRef {
|
||||
pub fn object_at(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
) -> Option<&RenderPipelineColorAttachmentDescriptorRef> {
|
||||
unsafe { msg_send![self, objectAtIndexedSubscript: index] }
|
||||
}
|
||||
|
||||
pub fn set_object_at(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
attachment: Option<&RenderPipelineColorAttachmentDescriptorRef>,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self, setObject:attachment
|
||||
atIndexedSubscript:index]
|
||||
}
|
||||
}
|
||||
}
|
||||
443
third-party/vendor/metal/src/renderpass.rs
vendored
Normal file
443
third-party/vendor/metal/src/renderpass.rs
vendored
Normal file
|
|
@ -0,0 +1,443 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlloadaction>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum MTLLoadAction {
|
||||
DontCare = 0,
|
||||
Load = 1,
|
||||
Clear = 2,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlstoreaction>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum MTLStoreAction {
|
||||
DontCare = 0,
|
||||
Store = 1,
|
||||
MultisampleResolve = 2,
|
||||
StoreAndMultisampleResolve = 3,
|
||||
Unknown = 4,
|
||||
CustomSampleDepthStore = 5,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlclearcolor>
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct MTLClearColor {
|
||||
pub red: f64,
|
||||
pub green: f64,
|
||||
pub blue: f64,
|
||||
pub alpha: f64,
|
||||
}
|
||||
|
||||
impl MTLClearColor {
|
||||
#[inline]
|
||||
pub fn new(red: f64, green: f64, blue: f64, alpha: f64) -> Self {
|
||||
Self {
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
alpha,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlmultisamplestencilresolvefilter>
|
||||
#[repr(u32)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum MTLMultisampleStencilResolveFilter {
|
||||
Sample0 = 0,
|
||||
DepthResolvedSample = 1,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderpassattachmentdescriptor>
|
||||
pub enum MTLRenderPassAttachmentDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLRenderPassAttachmentDescriptor;
|
||||
pub struct RenderPassAttachmentDescriptor;
|
||||
}
|
||||
|
||||
impl RenderPassAttachmentDescriptorRef {
|
||||
pub fn texture(&self) -> Option<&TextureRef> {
|
||||
unsafe { msg_send![self, texture] }
|
||||
}
|
||||
|
||||
pub fn set_texture(&self, texture: Option<&TextureRef>) {
|
||||
unsafe { msg_send![self, setTexture: texture] }
|
||||
}
|
||||
|
||||
pub fn level(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, level] }
|
||||
}
|
||||
|
||||
pub fn set_level(&self, level: NSUInteger) {
|
||||
unsafe { msg_send![self, setLevel: level] }
|
||||
}
|
||||
|
||||
pub fn slice(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, slice] }
|
||||
}
|
||||
|
||||
pub fn set_slice(&self, slice: NSUInteger) {
|
||||
unsafe { msg_send![self, setSlice: slice] }
|
||||
}
|
||||
|
||||
pub fn depth_plane(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, depthPlane] }
|
||||
}
|
||||
|
||||
pub fn set_depth_plane(&self, depth_plane: NSUInteger) {
|
||||
unsafe { msg_send![self, setDepthPlane: depth_plane] }
|
||||
}
|
||||
|
||||
pub fn resolve_texture(&self) -> Option<&TextureRef> {
|
||||
unsafe { msg_send![self, resolveTexture] }
|
||||
}
|
||||
|
||||
pub fn set_resolve_texture(&self, resolve_texture: Option<&TextureRef>) {
|
||||
unsafe { msg_send![self, setResolveTexture: resolve_texture] }
|
||||
}
|
||||
|
||||
pub fn resolve_level(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, resolveLevel] }
|
||||
}
|
||||
|
||||
pub fn set_resolve_level(&self, resolve_level: NSUInteger) {
|
||||
unsafe { msg_send![self, setResolveLevel: resolve_level] }
|
||||
}
|
||||
|
||||
pub fn resolve_slice(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, resolveSlice] }
|
||||
}
|
||||
|
||||
pub fn set_resolve_slice(&self, resolve_slice: NSUInteger) {
|
||||
unsafe { msg_send![self, setResolveSlice: resolve_slice] }
|
||||
}
|
||||
|
||||
pub fn resolve_depth_plane(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, resolveDepthPlane] }
|
||||
}
|
||||
|
||||
pub fn set_resolve_depth_plane(&self, resolve_depth_plane: NSUInteger) {
|
||||
unsafe { msg_send![self, setResolveDepthPlane: resolve_depth_plane] }
|
||||
}
|
||||
|
||||
pub fn load_action(&self) -> MTLLoadAction {
|
||||
unsafe { msg_send![self, loadAction] }
|
||||
}
|
||||
|
||||
pub fn set_load_action(&self, load_action: MTLLoadAction) {
|
||||
unsafe { msg_send![self, setLoadAction: load_action] }
|
||||
}
|
||||
|
||||
pub fn store_action(&self) -> MTLStoreAction {
|
||||
unsafe { msg_send![self, storeAction] }
|
||||
}
|
||||
|
||||
pub fn set_store_action(&self, store_action: MTLStoreAction) {
|
||||
unsafe { msg_send![self, setStoreAction: store_action] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderpasscolorattachmentdescriptor>
|
||||
pub enum MTLRenderPassColorAttachmentDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLRenderPassColorAttachmentDescriptor;
|
||||
pub struct RenderPassColorAttachmentDescriptor;
|
||||
type ParentType = RenderPassAttachmentDescriptor;
|
||||
}
|
||||
|
||||
impl RenderPassColorAttachmentDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLRenderPassColorAttachmentDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderPassColorAttachmentDescriptorRef {
|
||||
pub fn clear_color(&self) -> MTLClearColor {
|
||||
unsafe { msg_send![self, clearColor] }
|
||||
}
|
||||
|
||||
pub fn set_clear_color(&self, clear_color: MTLClearColor) {
|
||||
unsafe { msg_send![self, setClearColor: clear_color] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderpassdepthattachmentdescriptor>
|
||||
pub enum MTLRenderPassDepthAttachmentDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLRenderPassDepthAttachmentDescriptor;
|
||||
pub struct RenderPassDepthAttachmentDescriptor;
|
||||
type ParentType = RenderPassAttachmentDescriptor;
|
||||
}
|
||||
|
||||
impl RenderPassDepthAttachmentDescriptorRef {
|
||||
pub fn clear_depth(&self) -> f64 {
|
||||
unsafe { msg_send![self, clearDepth] }
|
||||
}
|
||||
|
||||
pub fn set_clear_depth(&self, clear_depth: f64) {
|
||||
unsafe { msg_send![self, setClearDepth: clear_depth] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderpassstencilattachmentdescriptor>
|
||||
pub enum MTLRenderPassStencilAttachmentDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLRenderPassStencilAttachmentDescriptor;
|
||||
pub struct RenderPassStencilAttachmentDescriptor;
|
||||
type ParentType = RenderPassAttachmentDescriptor;
|
||||
}
|
||||
|
||||
impl RenderPassStencilAttachmentDescriptorRef {
|
||||
pub fn clear_stencil(&self) -> u32 {
|
||||
unsafe { msg_send![self, clearStencil] }
|
||||
}
|
||||
|
||||
pub fn set_clear_stencil(&self, clear_stencil: u32) {
|
||||
unsafe { msg_send![self, setClearStencil: clear_stencil] }
|
||||
}
|
||||
|
||||
pub fn stencil_resolve_filter(&self) -> MTLMultisampleStencilResolveFilter {
|
||||
unsafe { msg_send![self, stencilResolveFilter] }
|
||||
}
|
||||
|
||||
pub fn set_stencil_resolve_filter(
|
||||
&self,
|
||||
stencil_resolve_filter: MTLMultisampleStencilResolveFilter,
|
||||
) {
|
||||
unsafe { msg_send![self, setStencilResolveFilter: stencil_resolve_filter] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderpasscolorattachmentdescriptorarray>
|
||||
pub enum MTLRenderPassColorAttachmentDescriptorArray {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLRenderPassColorAttachmentDescriptorArray;
|
||||
pub struct RenderPassColorAttachmentDescriptorArray;
|
||||
}
|
||||
|
||||
impl RenderPassColorAttachmentDescriptorArrayRef {
|
||||
pub fn object_at(&self, index: NSUInteger) -> Option<&RenderPassColorAttachmentDescriptorRef> {
|
||||
unsafe { msg_send![self, objectAtIndexedSubscript: index] }
|
||||
}
|
||||
|
||||
pub fn set_object_at(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
attachment: Option<&RenderPassColorAttachmentDescriptorRef>,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self, setObject:attachment
|
||||
atIndexedSubscript:index]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderpasssamplebufferattachmentdescriptor>
|
||||
pub enum MTLRenderPassSampleBufferAttachmentDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLRenderPassSampleBufferAttachmentDescriptor;
|
||||
pub struct RenderPassSampleBufferAttachmentDescriptor;
|
||||
}
|
||||
|
||||
impl RenderPassSampleBufferAttachmentDescriptor {
|
||||
pub fn new() -> Self {
|
||||
let class = class!(MTLRenderPassSampleBufferAttachmentDescriptor);
|
||||
unsafe { msg_send![class, new] }
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderPassSampleBufferAttachmentDescriptorRef {
|
||||
pub fn sample_buffer(&self) -> &CounterSampleBufferRef {
|
||||
unsafe { msg_send![self, sampleBuffer] }
|
||||
}
|
||||
|
||||
pub fn set_sample_buffer(&self, sample_buffer: &CounterSampleBufferRef) {
|
||||
unsafe { msg_send![self, setSampleBuffer: sample_buffer] }
|
||||
}
|
||||
|
||||
pub fn start_of_vertex_sample_index(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, startOfVertexSampleIndex] }
|
||||
}
|
||||
|
||||
pub fn set_start_of_vertex_sample_index(&self, start_of_vertex_sample_index: NSUInteger) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
setStartOfVertexSampleIndex: start_of_vertex_sample_index
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end_of_vertex_sample_index(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, endOfVertexSampleIndex] }
|
||||
}
|
||||
|
||||
pub fn set_end_of_vertex_sample_index(&self, end_of_vertex_sample_index: NSUInteger) {
|
||||
unsafe { msg_send![self, setEndOfVertexSampleIndex: end_of_vertex_sample_index] }
|
||||
}
|
||||
|
||||
pub fn start_of_fragment_sample_index(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, startOfFragmentSampleIndex] }
|
||||
}
|
||||
|
||||
pub fn set_start_of_fragment_sample_index(&self, start_of_fragment_sample_index: NSUInteger) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
setStartOfFragmentSampleIndex: start_of_fragment_sample_index
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end_of_fragment_sample_index(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, endOfFragmentSampleIndex] }
|
||||
}
|
||||
|
||||
pub fn set_end_of_fragment_sample_index(&self, end_of_fragment_sample_index: NSUInteger) {
|
||||
unsafe {
|
||||
msg_send![
|
||||
self,
|
||||
setEndOfFragmentSampleIndex: end_of_fragment_sample_index
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderpasssamplebufferattachmentdescriptorarray>
|
||||
pub enum MTLRenderPassSampleBufferAttachmentDescriptorArray {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLRenderPassSampleBufferAttachmentDescriptorArray;
|
||||
pub struct RenderPassSampleBufferAttachmentDescriptorArray;
|
||||
}
|
||||
|
||||
impl RenderPassSampleBufferAttachmentDescriptorArrayRef {
|
||||
pub fn object_at(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
) -> Option<&RenderPassSampleBufferAttachmentDescriptorRef> {
|
||||
unsafe { msg_send![self, objectAtIndexedSubscript: index] }
|
||||
}
|
||||
|
||||
pub fn set_object_at(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
attachment: Option<&RenderPassSampleBufferAttachmentDescriptorRef>,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self, setObject:attachment
|
||||
atIndexedSubscript:index]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// ## Important!
|
||||
/// When configuring a [`MTLTextureDescriptor`] object for use with an attachment, set its usage
|
||||
/// value to renderTarget if you already know that you intend to use the resulting MTLTexture object in
|
||||
/// an attachment. This may significantly improve your app’s performance with certain hardware.
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderpassdescriptor>
|
||||
pub enum MTLRenderPassDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLRenderPassDescriptor;
|
||||
pub struct RenderPassDescriptor;
|
||||
}
|
||||
|
||||
impl RenderPassDescriptor {
|
||||
/// Creates a default render pass descriptor with no attachments.
|
||||
pub fn new<'a>() -> &'a RenderPassDescriptorRef {
|
||||
unsafe { msg_send![class!(MTLRenderPassDescriptor), renderPassDescriptor] }
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderPassDescriptorRef {
|
||||
pub fn color_attachments(&self) -> &RenderPassColorAttachmentDescriptorArrayRef {
|
||||
unsafe { msg_send![self, colorAttachments] }
|
||||
}
|
||||
|
||||
pub fn depth_attachment(&self) -> Option<&RenderPassDepthAttachmentDescriptorRef> {
|
||||
unsafe { msg_send![self, depthAttachment] }
|
||||
}
|
||||
|
||||
pub fn set_depth_attachment(
|
||||
&self,
|
||||
depth_attachment: Option<&RenderPassDepthAttachmentDescriptorRef>,
|
||||
) {
|
||||
unsafe { msg_send![self, setDepthAttachment: depth_attachment] }
|
||||
}
|
||||
|
||||
pub fn stencil_attachment(&self) -> Option<&RenderPassStencilAttachmentDescriptorRef> {
|
||||
unsafe { msg_send![self, stencilAttachment] }
|
||||
}
|
||||
|
||||
pub fn set_stencil_attachment(
|
||||
&self,
|
||||
stencil_attachment: Option<&RenderPassStencilAttachmentDescriptorRef>,
|
||||
) {
|
||||
unsafe { msg_send![self, setStencilAttachment: stencil_attachment] }
|
||||
}
|
||||
|
||||
pub fn visibility_result_buffer(&self) -> Option<&BufferRef> {
|
||||
unsafe { msg_send![self, visibilityResultBuffer] }
|
||||
}
|
||||
|
||||
pub fn set_visibility_result_buffer(&self, buffer: Option<&BufferRef>) {
|
||||
unsafe { msg_send![self, setVisibilityResultBuffer: buffer] }
|
||||
}
|
||||
|
||||
pub fn render_target_array_length(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, renderTargetArrayLength] }
|
||||
}
|
||||
|
||||
pub fn set_render_target_array_length(&self, length: NSUInteger) {
|
||||
unsafe { msg_send![self, setRenderTargetArrayLength: length] }
|
||||
}
|
||||
|
||||
pub fn render_target_width(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, renderTargetWidth] }
|
||||
}
|
||||
|
||||
pub fn set_render_target_width(&self, size: NSUInteger) {
|
||||
unsafe { msg_send![self, setRenderTargetWidth: size] }
|
||||
}
|
||||
|
||||
pub fn render_target_height(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, renderTargetHeight] }
|
||||
}
|
||||
|
||||
pub fn set_render_target_height(&self, size: NSUInteger) {
|
||||
unsafe { msg_send![self, setRenderTargetHeight: size] }
|
||||
}
|
||||
|
||||
pub fn default_raster_sample_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, defaultRasterSampleCount] }
|
||||
}
|
||||
|
||||
pub fn set_default_raster_sample_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setDefaultRasterSampleCount: count] }
|
||||
}
|
||||
|
||||
pub fn sample_buffer_attachments(&self) -> &RenderPassSampleBufferAttachmentDescriptorArrayRef {
|
||||
unsafe { msg_send![self, sampleBufferAttachments] }
|
||||
}
|
||||
}
|
||||
182
third-party/vendor/metal/src/resource.rs
vendored
Normal file
182
third-party/vendor/metal/src/resource.rs
vendored
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
use objc::runtime::{NO, YES};
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlpurgeablestate>
|
||||
#[repr(u64)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum MTLPurgeableState {
|
||||
KeepCurrent = 1,
|
||||
NonVolatile = 2,
|
||||
Volatile = 3,
|
||||
Empty = 4,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlcpucachemode>
|
||||
#[repr(u64)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum MTLCPUCacheMode {
|
||||
DefaultCache = 0,
|
||||
WriteCombined = 1,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlstoragemode>
|
||||
#[repr(u64)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum MTLStorageMode {
|
||||
Shared = 0,
|
||||
Managed = 1,
|
||||
Private = 2,
|
||||
/// Only available on macos(11.0), macCatalyst(14.0), ios(10.0)
|
||||
Memoryless = 3,
|
||||
}
|
||||
|
||||
/// Only available on macos(10.15), ios(13.0)
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlhazardtrackingmode>
|
||||
#[repr(u64)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum MTLHazardTrackingMode {
|
||||
Default = 0,
|
||||
Untracked = 1,
|
||||
Tracked = 2,
|
||||
}
|
||||
|
||||
pub const MTLResourceCPUCacheModeShift: NSUInteger = 0;
|
||||
pub const MTLResourceCPUCacheModeMask: NSUInteger = 0xf << MTLResourceCPUCacheModeShift;
|
||||
pub const MTLResourceStorageModeShift: NSUInteger = 4;
|
||||
pub const MTLResourceStorageModeMask: NSUInteger = 0xf << MTLResourceStorageModeShift;
|
||||
pub const MTLResourceHazardTrackingModeShift: NSUInteger = 8;
|
||||
pub const MTLResourceHazardTrackingModeMask: NSUInteger = 0x3 << MTLResourceHazardTrackingModeShift;
|
||||
|
||||
bitflags! {
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlresourceoptions>
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct MTLResourceOptions: NSUInteger {
|
||||
const CPUCacheModeDefaultCache = (MTLCPUCacheMode::DefaultCache as NSUInteger) << MTLResourceCPUCacheModeShift;
|
||||
const CPUCacheModeWriteCombined = (MTLCPUCacheMode::WriteCombined as NSUInteger) << MTLResourceCPUCacheModeShift;
|
||||
|
||||
const StorageModeShared = (MTLStorageMode::Shared as NSUInteger) << MTLResourceStorageModeShift;
|
||||
const StorageModeManaged = (MTLStorageMode::Managed as NSUInteger) << MTLResourceStorageModeShift;
|
||||
const StorageModePrivate = (MTLStorageMode::Private as NSUInteger) << MTLResourceStorageModeShift;
|
||||
const StorageModeMemoryless = (MTLStorageMode::Memoryless as NSUInteger) << MTLResourceStorageModeShift;
|
||||
|
||||
/// Only available on macos(10.13), ios(10.0)
|
||||
const HazardTrackingModeDefault = (MTLHazardTrackingMode::Default as NSUInteger) << MTLResourceHazardTrackingModeShift;
|
||||
/// Only available on macos(10.13), ios(10.0)
|
||||
const HazardTrackingModeUntracked = (MTLHazardTrackingMode::Untracked as NSUInteger) << MTLResourceHazardTrackingModeShift;
|
||||
/// Only available on macos(10.15), ios(13.0)
|
||||
const HazardTrackingModeTracked = (MTLHazardTrackingMode::Tracked as NSUInteger) << MTLResourceHazardTrackingModeShift;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Options that describe how a graphics or compute function uses an argument buffer’s resource.
|
||||
///
|
||||
/// Enabling certain options for certain resources determines whether the Metal driver should
|
||||
/// convert the resource to another format (for example, whether to decompress a color render target).
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlresourceusage>
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct MTLResourceUsage: NSUInteger {
|
||||
/// An option that enables reading from the resource.
|
||||
const Read = 1 << 0;
|
||||
/// An option that enables writing to the resource.
|
||||
const Write = 1 << 1;
|
||||
/// An option that enables sampling from the resource.
|
||||
///
|
||||
/// Specify this option only if the resource is a texture.
|
||||
const Sample = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlsizeandalign>
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct MTLSizeAndAlign {
|
||||
pub size: NSUInteger,
|
||||
pub align: NSUInteger,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlresource>
|
||||
pub enum MTLResource {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLResource;
|
||||
pub struct Resource;
|
||||
type ParentType = NsObject;
|
||||
}
|
||||
|
||||
impl ResourceRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cpu_cache_mode(&self) -> MTLCPUCacheMode {
|
||||
unsafe { msg_send![self, cpuCacheMode] }
|
||||
}
|
||||
|
||||
pub fn storage_mode(&self) -> MTLStorageMode {
|
||||
unsafe { msg_send![self, storageMode] }
|
||||
}
|
||||
|
||||
pub fn set_purgeable_state(&self, state: MTLPurgeableState) -> MTLPurgeableState {
|
||||
unsafe { msg_send![self, setPurgeableState: state] }
|
||||
}
|
||||
|
||||
/// Only available on macOS 10.13+ & iOS 10.11+
|
||||
pub fn allocated_size(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, allocatedSize] }
|
||||
}
|
||||
|
||||
/// Only available on macos(10.15), ios(13.0)
|
||||
pub fn hazard_tracking_mode(&self) -> MTLHazardTrackingMode {
|
||||
unsafe { msg_send![self, hazardTrackingMode] }
|
||||
}
|
||||
|
||||
/// Only available on macos(10.15), ios(13.0)
|
||||
pub fn resource_options(&self) -> MTLResourceOptions {
|
||||
unsafe { msg_send![self, resourceOptions] }
|
||||
}
|
||||
|
||||
/// Only available on macos(10.13), ios(10.0)
|
||||
pub fn heap(&self) -> &HeapRef {
|
||||
unsafe { msg_send![self, heap] }
|
||||
}
|
||||
|
||||
/// Only available on macos(10.15), ios(13.0)
|
||||
pub fn heap_offset(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, heapOffset] }
|
||||
}
|
||||
|
||||
/// Only available on macos(10.13), ios(10.0)
|
||||
pub fn make_aliasable(&self) {
|
||||
unsafe { msg_send![self, makeAliasable] }
|
||||
}
|
||||
|
||||
/// Only available on macos(10.13), ios(10.0)
|
||||
pub fn is_aliasable(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isAliasable] }
|
||||
}
|
||||
}
|
||||
161
third-party/vendor/metal/src/sampler.rs
vendored
Normal file
161
third-party/vendor/metal/src/sampler.rs
vendored
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::{depthstencil::MTLCompareFunction, DeviceRef, NSUInteger};
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlsamplerminmagfilter>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLSamplerMinMagFilter {
|
||||
Nearest = 0,
|
||||
Linear = 1,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlsamplermipfilter>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLSamplerMipFilter {
|
||||
NotMipmapped = 0,
|
||||
Nearest = 1,
|
||||
Linear = 2,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlsampleraddressmode>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLSamplerAddressMode {
|
||||
ClampToEdge = 0,
|
||||
MirrorClampToEdge = 1,
|
||||
Repeat = 2,
|
||||
MirrorRepeat = 3,
|
||||
ClampToZero = 4,
|
||||
ClampToBorderColor = 5,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlsamplerbordercolor>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLSamplerBorderColor {
|
||||
TransparentBlack = 0,
|
||||
OpaqueBlack = 1,
|
||||
OpaqueWhite = 2,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlsamplerdescriptor>
|
||||
pub enum MTLSamplerDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLSamplerDescriptor;
|
||||
pub struct SamplerDescriptor;
|
||||
}
|
||||
|
||||
impl SamplerDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLSamplerDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SamplerDescriptorRef {
|
||||
pub fn set_min_filter(&self, filter: MTLSamplerMinMagFilter) {
|
||||
unsafe { msg_send![self, setMinFilter: filter] }
|
||||
}
|
||||
|
||||
pub fn set_mag_filter(&self, filter: MTLSamplerMinMagFilter) {
|
||||
unsafe { msg_send![self, setMagFilter: filter] }
|
||||
}
|
||||
|
||||
pub fn set_mip_filter(&self, filter: MTLSamplerMipFilter) {
|
||||
unsafe { msg_send![self, setMipFilter: filter] }
|
||||
}
|
||||
|
||||
pub fn set_address_mode_s(&self, mode: MTLSamplerAddressMode) {
|
||||
unsafe { msg_send![self, setSAddressMode: mode] }
|
||||
}
|
||||
|
||||
pub fn set_address_mode_t(&self, mode: MTLSamplerAddressMode) {
|
||||
unsafe { msg_send![self, setTAddressMode: mode] }
|
||||
}
|
||||
|
||||
pub fn set_address_mode_r(&self, mode: MTLSamplerAddressMode) {
|
||||
unsafe { msg_send![self, setRAddressMode: mode] }
|
||||
}
|
||||
|
||||
pub fn set_max_anisotropy(&self, anisotropy: NSUInteger) {
|
||||
unsafe { msg_send![self, setMaxAnisotropy: anisotropy] }
|
||||
}
|
||||
|
||||
pub fn set_compare_function(&self, func: MTLCompareFunction) {
|
||||
unsafe { msg_send![self, setCompareFunction: func] }
|
||||
}
|
||||
|
||||
#[cfg(feature = "private")]
|
||||
pub unsafe fn set_lod_bias(&self, bias: f32) {
|
||||
msg_send![self, setLodBias: bias]
|
||||
}
|
||||
|
||||
pub fn set_lod_min_clamp(&self, clamp: f32) {
|
||||
unsafe { msg_send![self, setLodMinClamp: clamp] }
|
||||
}
|
||||
|
||||
pub fn set_lod_max_clamp(&self, clamp: f32) {
|
||||
unsafe { msg_send![self, setLodMaxClamp: clamp] }
|
||||
}
|
||||
|
||||
pub fn set_lod_average(&self, enable: bool) {
|
||||
unsafe { msg_send![self, setLodAverage: enable] }
|
||||
}
|
||||
|
||||
pub fn set_normalized_coordinates(&self, enable: bool) {
|
||||
unsafe { msg_send![self, setNormalizedCoordinates: enable] }
|
||||
}
|
||||
|
||||
pub fn set_support_argument_buffers(&self, enable: bool) {
|
||||
unsafe { msg_send![self, setSupportArgumentBuffers: enable] }
|
||||
}
|
||||
|
||||
pub fn set_border_color(&self, color: MTLSamplerBorderColor) {
|
||||
unsafe { msg_send![self, setBorderColor: color] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlsamplerstate>
|
||||
pub enum MTLSamplerState {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLSamplerState;
|
||||
pub struct SamplerState;
|
||||
}
|
||||
|
||||
impl SamplerStateRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
}
|
||||
178
third-party/vendor/metal/src/sync.rs
vendored
Normal file
178
third-party/vendor/metal/src/sync.rs
vendored
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
use block::{Block, RcBlock};
|
||||
use std::mem;
|
||||
|
||||
#[cfg(feature = "dispatch_queue")]
|
||||
use dispatch;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlsharedeventnotificationblock>
|
||||
type MTLSharedEventNotificationBlock<'a> = RcBlock<(&'a SharedEventRef, u64), ()>;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlevent>
|
||||
pub enum MTLEvent {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLEvent;
|
||||
pub struct Event;
|
||||
}
|
||||
|
||||
impl EventRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlsharedevent>
|
||||
pub enum MTLSharedEvent {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLSharedEvent;
|
||||
pub struct SharedEvent;
|
||||
type ParentType = Event;
|
||||
}
|
||||
|
||||
impl SharedEventRef {
|
||||
pub fn signaled_value(&self) -> u64 {
|
||||
unsafe { msg_send![self, signaledValue] }
|
||||
}
|
||||
|
||||
pub fn set_signaled_value(&self, new_value: u64) {
|
||||
unsafe { msg_send![self, setSignaledValue: new_value] }
|
||||
}
|
||||
|
||||
/// Schedules a notification handler to be called after the shareable event’s signal value
|
||||
/// equals or exceeds a given value.
|
||||
pub fn notify(
|
||||
&self,
|
||||
listener: &SharedEventListenerRef,
|
||||
value: u64,
|
||||
block: MTLSharedEventNotificationBlock,
|
||||
) {
|
||||
unsafe {
|
||||
// If the block doesn't have a signature, this segfaults.
|
||||
// Taken from https://github.com/servo/pathfinder/blob/e858c8dc1d8ff02a5b603e21e09a64d6b3e11327/metal/src/lib.rs#L2327
|
||||
let block = mem::transmute::<
|
||||
MTLSharedEventNotificationBlock,
|
||||
*mut BlockBase<(&SharedEventRef, u64), ()>,
|
||||
>(block);
|
||||
(*block).flags |= BLOCK_HAS_SIGNATURE | BLOCK_HAS_COPY_DISPOSE;
|
||||
(*block).extra = &BLOCK_EXTRA;
|
||||
let () = msg_send![self, notifyListener:listener atValue:value block:block];
|
||||
}
|
||||
|
||||
extern "C" fn dtor(_: *mut BlockBase<(&SharedEventRef, u64), ()>) {}
|
||||
|
||||
const SIGNATURE: &[u8] = b"v16@?0Q8\0";
|
||||
const SIGNATURE_PTR: *const i8 = &SIGNATURE[0] as *const u8 as *const i8;
|
||||
static mut BLOCK_EXTRA: BlockExtra<(&SharedEventRef, u64), ()> = BlockExtra {
|
||||
unknown0: 0 as *mut i32,
|
||||
unknown1: 0 as *mut i32,
|
||||
unknown2: 0 as *mut i32,
|
||||
dtor,
|
||||
signature: &SIGNATURE_PTR,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlsharedeventlistener>
|
||||
pub enum MTLSharedEventListener {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLSharedEventListener;
|
||||
pub struct SharedEventListener;
|
||||
}
|
||||
|
||||
impl SharedEventListener {
|
||||
pub unsafe fn from_queue_handle(queue: dispatch_queue_t) -> Self {
|
||||
let listener: SharedEventListener = msg_send![class!(MTLSharedEventListener), alloc];
|
||||
let ptr: *mut Object = msg_send![listener.as_ref(), initWithDispatchQueue: queue];
|
||||
if ptr.is_null() {
|
||||
panic!("[MTLSharedEventListener alloc] initWithDispatchQueue failed");
|
||||
}
|
||||
listener
|
||||
}
|
||||
|
||||
#[cfg(feature = "dispatch")]
|
||||
pub fn from_queue(queue: &dispatch::Queue) -> Self {
|
||||
unsafe {
|
||||
let raw_queue = std::mem::transmute::<&dispatch::Queue, *const dispatch_queue_t>(queue);
|
||||
Self::from_queue_handle(*raw_queue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlfence>
|
||||
pub enum MTLFence {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLFence;
|
||||
pub struct Fence;
|
||||
}
|
||||
|
||||
impl FenceRef {
|
||||
pub fn device(&self) -> &DeviceRef {
|
||||
unsafe { msg_send![self, device] }
|
||||
}
|
||||
|
||||
pub fn label(&self) -> &str {
|
||||
unsafe {
|
||||
let label = msg_send![self, label];
|
||||
crate::nsstring_as_str(label)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_label(&self, label: &str) {
|
||||
unsafe {
|
||||
let nslabel = crate::nsstring_from_str(label);
|
||||
let () = msg_send![self, setLabel: nslabel];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// The render stages at which a synchronization command is triggered.
|
||||
///
|
||||
/// Render stages provide finer control for specifying when synchronization must occur,
|
||||
/// allowing for vertex and fragment processing to overlap in execution.
|
||||
///
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlrenderstages>
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct MTLRenderStages: NSUInteger {
|
||||
/// The vertex rendering stage.
|
||||
const Vertex = 1 << 0;
|
||||
/// The fragment rendering stage.
|
||||
const Fragment = 1 << 1;
|
||||
/// The tile rendering stage.
|
||||
const Tile = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
const BLOCK_HAS_COPY_DISPOSE: i32 = 0x02000000;
|
||||
const BLOCK_HAS_SIGNATURE: i32 = 0x40000000;
|
||||
|
||||
#[repr(C)]
|
||||
struct BlockBase<A, R> {
|
||||
isa: *const std::ffi::c_void, // 0x00
|
||||
flags: i32, // 0x08
|
||||
_reserved: i32, // 0x0c
|
||||
invoke: unsafe extern "C" fn(*mut Block<A, R>, ...) -> R, // 0x10
|
||||
extra: *const BlockExtra<A, R>, // 0x18
|
||||
}
|
||||
|
||||
type BlockExtraDtor<A, R> = extern "C" fn(*mut BlockBase<A, R>);
|
||||
|
||||
#[repr(C)]
|
||||
struct BlockExtra<A, R> {
|
||||
unknown0: *mut i32, // 0x00
|
||||
unknown1: *mut i32, // 0x08
|
||||
unknown2: *mut i32, // 0x10
|
||||
dtor: BlockExtraDtor<A, R>, // 0x18
|
||||
signature: *const *const i8, // 0x20
|
||||
}
|
||||
351
third-party/vendor/metal/src/texture.rs
vendored
Normal file
351
third-party/vendor/metal/src/texture.rs
vendored
Normal file
|
|
@ -0,0 +1,351 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::*;
|
||||
|
||||
use objc::runtime::{NO, YES};
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtltexturetype>
|
||||
#[repr(u64)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub enum MTLTextureType {
|
||||
D1 = 0,
|
||||
D1Array = 1,
|
||||
D2 = 2,
|
||||
D2Array = 3,
|
||||
D2Multisample = 4,
|
||||
Cube = 5,
|
||||
CubeArray = 6,
|
||||
D3 = 7,
|
||||
D2MultisampleArray = 8,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtltexturecompressiontype>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub enum MTLTextureCompressionType {
|
||||
Lossless = 0,
|
||||
Lossy = 1,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// See <https://developer.apple.com/documentation/metal/mtltextureusage>
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct MTLTextureUsage: NSUInteger {
|
||||
const Unknown = 0x0000;
|
||||
const ShaderRead = 0x0001;
|
||||
const ShaderWrite = 0x0002;
|
||||
const RenderTarget = 0x0004;
|
||||
const PixelFormatView = 0x0010;
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtltexturedescriptor>
|
||||
pub enum MTLTextureDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLTextureDescriptor;
|
||||
pub struct TextureDescriptor;
|
||||
}
|
||||
|
||||
impl TextureDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLTextureDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TextureDescriptorRef {
|
||||
pub fn texture_type(&self) -> MTLTextureType {
|
||||
unsafe { msg_send![self, textureType] }
|
||||
}
|
||||
|
||||
pub fn set_texture_type(&self, texture_type: MTLTextureType) {
|
||||
unsafe { msg_send![self, setTextureType: texture_type] }
|
||||
}
|
||||
|
||||
pub fn pixel_format(&self) -> MTLPixelFormat {
|
||||
unsafe { msg_send![self, pixelFormat] }
|
||||
}
|
||||
|
||||
pub fn set_pixel_format(&self, pixel_format: MTLPixelFormat) {
|
||||
unsafe { msg_send![self, setPixelFormat: pixel_format] }
|
||||
}
|
||||
|
||||
pub fn width(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, width] }
|
||||
}
|
||||
|
||||
pub fn set_width(&self, width: NSUInteger) {
|
||||
unsafe { msg_send![self, setWidth: width] }
|
||||
}
|
||||
|
||||
pub fn height(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, height] }
|
||||
}
|
||||
|
||||
pub fn set_height(&self, height: NSUInteger) {
|
||||
unsafe { msg_send![self, setHeight: height] }
|
||||
}
|
||||
|
||||
pub fn depth(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, depth] }
|
||||
}
|
||||
|
||||
pub fn set_depth(&self, depth: NSUInteger) {
|
||||
unsafe { msg_send![self, setDepth: depth] }
|
||||
}
|
||||
|
||||
pub fn mipmap_level_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, mipmapLevelCount] }
|
||||
}
|
||||
|
||||
pub fn set_mipmap_level_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setMipmapLevelCount: count] }
|
||||
}
|
||||
|
||||
pub fn set_mipmap_level_count_for_size(&self, size: MTLSize) {
|
||||
let MTLSize {
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
} = size;
|
||||
let count = (width.max(height).max(depth) as f64).log2().ceil() as u64;
|
||||
self.set_mipmap_level_count(count);
|
||||
}
|
||||
|
||||
pub fn sample_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, sampleCount] }
|
||||
}
|
||||
|
||||
pub fn set_sample_count(&self, count: NSUInteger) {
|
||||
unsafe { msg_send![self, setSampleCount: count] }
|
||||
}
|
||||
|
||||
pub fn array_length(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, arrayLength] }
|
||||
}
|
||||
|
||||
pub fn set_array_length(&self, length: NSUInteger) {
|
||||
unsafe { msg_send![self, setArrayLength: length] }
|
||||
}
|
||||
|
||||
pub fn resource_options(&self) -> MTLResourceOptions {
|
||||
unsafe { msg_send![self, resourceOptions] }
|
||||
}
|
||||
|
||||
pub fn set_resource_options(&self, options: MTLResourceOptions) {
|
||||
unsafe { msg_send![self, setResourceOptions: options] }
|
||||
}
|
||||
|
||||
pub fn cpu_cache_mode(&self) -> MTLCPUCacheMode {
|
||||
unsafe { msg_send![self, cpuCacheMode] }
|
||||
}
|
||||
|
||||
pub fn set_cpu_cache_mode(&self, mode: MTLCPUCacheMode) {
|
||||
unsafe { msg_send![self, setCpuCacheMode: mode] }
|
||||
}
|
||||
|
||||
pub fn storage_mode(&self) -> MTLStorageMode {
|
||||
unsafe { msg_send![self, storageMode] }
|
||||
}
|
||||
|
||||
pub fn set_storage_mode(&self, mode: MTLStorageMode) {
|
||||
unsafe { msg_send![self, setStorageMode: mode] }
|
||||
}
|
||||
|
||||
pub fn usage(&self) -> MTLTextureUsage {
|
||||
unsafe { msg_send![self, usage] }
|
||||
}
|
||||
|
||||
pub fn set_usage(&self, usage: MTLTextureUsage) {
|
||||
unsafe { msg_send![self, setUsage: usage] }
|
||||
}
|
||||
|
||||
pub fn compression_type(&self) -> MTLTextureCompressionType {
|
||||
unsafe { msg_send![self, compressionType] }
|
||||
}
|
||||
|
||||
pub fn set_compression_type(&self, compression_type: MTLTextureCompressionType) {
|
||||
unsafe { msg_send![self, setCompressionType: compression_type] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtltexture>
|
||||
pub enum MTLTexture {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLTexture;
|
||||
pub struct Texture;
|
||||
type ParentType = Resource;
|
||||
}
|
||||
|
||||
impl TextureRef {
|
||||
#[deprecated(since = "0.13.0")]
|
||||
pub fn root_resource(&self) -> Option<&ResourceRef> {
|
||||
unsafe { msg_send![self, rootResource] }
|
||||
}
|
||||
|
||||
pub fn parent_texture(&self) -> Option<&TextureRef> {
|
||||
unsafe { msg_send![self, parentTexture] }
|
||||
}
|
||||
|
||||
pub fn parent_relative_level(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, parentRelativeLevel] }
|
||||
}
|
||||
|
||||
pub fn parent_relative_slice(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, parentRelativeSlice] }
|
||||
}
|
||||
|
||||
pub fn buffer(&self) -> Option<&BufferRef> {
|
||||
unsafe { msg_send![self, buffer] }
|
||||
}
|
||||
|
||||
pub fn buffer_offset(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, bufferOffset] }
|
||||
}
|
||||
|
||||
pub fn buffer_stride(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, bufferBytesPerRow] }
|
||||
}
|
||||
|
||||
pub fn texture_type(&self) -> MTLTextureType {
|
||||
unsafe { msg_send![self, textureType] }
|
||||
}
|
||||
|
||||
pub fn pixel_format(&self) -> MTLPixelFormat {
|
||||
unsafe { msg_send![self, pixelFormat] }
|
||||
}
|
||||
|
||||
pub fn width(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, width] }
|
||||
}
|
||||
|
||||
pub fn height(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, height] }
|
||||
}
|
||||
|
||||
pub fn depth(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, depth] }
|
||||
}
|
||||
|
||||
pub fn mipmap_level_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, mipmapLevelCount] }
|
||||
}
|
||||
|
||||
pub fn sample_count(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, sampleCount] }
|
||||
}
|
||||
|
||||
pub fn array_length(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, arrayLength] }
|
||||
}
|
||||
|
||||
pub fn usage(&self) -> MTLTextureUsage {
|
||||
unsafe { msg_send![self, usage] }
|
||||
}
|
||||
|
||||
/// [framebufferOnly Apple Docs](https://developer.apple.com/documentation/metal/mtltexture/1515749-framebufferonly?language=objc)
|
||||
pub fn framebuffer_only(&self) -> bool {
|
||||
unsafe { msg_send_bool![self, isFramebufferOnly] }
|
||||
}
|
||||
|
||||
pub fn get_bytes(
|
||||
&self,
|
||||
bytes: *mut std::ffi::c_void,
|
||||
stride: NSUInteger,
|
||||
region: MTLRegion,
|
||||
mipmap_level: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self, getBytes:bytes
|
||||
bytesPerRow:stride
|
||||
fromRegion:region
|
||||
mipmapLevel:mipmap_level]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_bytes_in_slice(
|
||||
&self,
|
||||
bytes: *mut std::ffi::c_void,
|
||||
stride: NSUInteger,
|
||||
image_stride: NSUInteger,
|
||||
region: MTLRegion,
|
||||
mipmap_level: NSUInteger,
|
||||
slice: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self, getBytes:bytes
|
||||
bytesPerRow:stride
|
||||
bytesPerImage:image_stride
|
||||
fromRegion:region
|
||||
mipmapLevel:mipmap_level
|
||||
slice:slice]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn replace_region(
|
||||
&self,
|
||||
region: MTLRegion,
|
||||
mipmap_level: NSUInteger,
|
||||
bytes: *const std::ffi::c_void,
|
||||
stride: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self, replaceRegion:region
|
||||
mipmapLevel:mipmap_level
|
||||
withBytes:bytes
|
||||
bytesPerRow:stride]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn replace_region_in_slice(
|
||||
&self,
|
||||
region: MTLRegion,
|
||||
mipmap_level: NSUInteger,
|
||||
slice: NSUInteger,
|
||||
bytes: *const std::ffi::c_void,
|
||||
stride: NSUInteger,
|
||||
image_stride: NSUInteger,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self, replaceRegion:region
|
||||
mipmapLevel:mipmap_level
|
||||
slice:slice
|
||||
withBytes:bytes
|
||||
bytesPerRow:stride
|
||||
bytesPerImage:image_stride]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_texture_view(&self, pixel_format: MTLPixelFormat) -> Texture {
|
||||
unsafe { msg_send![self, newTextureViewWithPixelFormat: pixel_format] }
|
||||
}
|
||||
|
||||
pub fn new_texture_view_from_slice(
|
||||
&self,
|
||||
pixel_format: MTLPixelFormat,
|
||||
texture_type: MTLTextureType,
|
||||
mipmap_levels: crate::NSRange,
|
||||
slices: crate::NSRange,
|
||||
) -> Texture {
|
||||
unsafe {
|
||||
msg_send![self, newTextureViewWithPixelFormat:pixel_format
|
||||
textureType:texture_type
|
||||
levels:mipmap_levels
|
||||
slices:slices]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gpu_resource_id(&self) -> MTLResourceID {
|
||||
unsafe { msg_send![self, gpuResourceID] }
|
||||
}
|
||||
}
|
||||
90
third-party/vendor/metal/src/types.rs
vendored
Normal file
90
third-party/vendor/metal/src/types.rs
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::NSUInteger;
|
||||
use std::default::Default;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlorigin>
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Default)]
|
||||
pub struct MTLOrigin {
|
||||
pub x: NSUInteger,
|
||||
pub y: NSUInteger,
|
||||
pub z: NSUInteger,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlsize>
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Default)]
|
||||
pub struct MTLSize {
|
||||
pub width: NSUInteger,
|
||||
pub height: NSUInteger,
|
||||
pub depth: NSUInteger,
|
||||
}
|
||||
|
||||
impl MTLSize {
|
||||
pub fn new(width: NSUInteger, height: NSUInteger, depth: NSUInteger) -> Self {
|
||||
Self {
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlregion>
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Default)]
|
||||
pub struct MTLRegion {
|
||||
pub origin: MTLOrigin,
|
||||
pub size: MTLSize,
|
||||
}
|
||||
|
||||
impl MTLRegion {
|
||||
#[inline]
|
||||
pub fn new_1d(x: NSUInteger, width: NSUInteger) -> Self {
|
||||
Self::new_2d(x, 0, width, 1)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_2d(x: NSUInteger, y: NSUInteger, width: NSUInteger, height: NSUInteger) -> Self {
|
||||
Self::new_3d(x, y, 0, width, height, 1)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_3d(
|
||||
x: NSUInteger,
|
||||
y: NSUInteger,
|
||||
z: NSUInteger,
|
||||
width: NSUInteger,
|
||||
height: NSUInteger,
|
||||
depth: NSUInteger,
|
||||
) -> Self {
|
||||
Self {
|
||||
origin: MTLOrigin { x, y, z },
|
||||
size: MTLSize {
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlsampleposition>
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Default)]
|
||||
pub struct MTLSamplePosition {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Default)]
|
||||
pub struct MTLResourceID {
|
||||
pub _impl: u64,
|
||||
}
|
||||
250
third-party/vendor/metal/src/vertexdescriptor.rs
vendored
Normal file
250
third-party/vendor/metal/src/vertexdescriptor.rs
vendored
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
// Copyright 2016 GFX developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use super::NSUInteger;
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlvertexformat>
|
||||
#[repr(u64)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLVertexFormat {
|
||||
Invalid = 0,
|
||||
UChar2 = 1,
|
||||
UChar3 = 2,
|
||||
UChar4 = 3,
|
||||
Char2 = 4,
|
||||
Char3 = 5,
|
||||
Char4 = 6,
|
||||
UChar2Normalized = 7,
|
||||
UChar3Normalized = 8,
|
||||
UChar4Normalized = 9,
|
||||
Char2Normalized = 10,
|
||||
Char3Normalized = 11,
|
||||
Char4Normalized = 12,
|
||||
UShort2 = 13,
|
||||
UShort3 = 14,
|
||||
UShort4 = 15,
|
||||
Short2 = 16,
|
||||
Short3 = 17,
|
||||
Short4 = 18,
|
||||
UShort2Normalized = 19,
|
||||
UShort3Normalized = 20,
|
||||
UShort4Normalized = 21,
|
||||
Short2Normalized = 22,
|
||||
Short3Normalized = 23,
|
||||
Short4Normalized = 24,
|
||||
Half2 = 25,
|
||||
Half3 = 26,
|
||||
Half4 = 27,
|
||||
Float = 28,
|
||||
Float2 = 29,
|
||||
Float3 = 30,
|
||||
Float4 = 31,
|
||||
Int = 32,
|
||||
Int2 = 33,
|
||||
Int3 = 34,
|
||||
Int4 = 35,
|
||||
UInt = 36,
|
||||
UInt2 = 37,
|
||||
UInt3 = 38,
|
||||
UInt4 = 39,
|
||||
Int1010102Normalized = 40,
|
||||
UInt1010102Normalized = 41,
|
||||
UChar4Normalized_BGRA = 42,
|
||||
UChar = 45,
|
||||
Char = 46,
|
||||
UCharNormalized = 47,
|
||||
CharNormalized = 48,
|
||||
UShort = 49,
|
||||
Short = 50,
|
||||
UShortNormalized = 51,
|
||||
ShortNormalized = 52,
|
||||
Half = 53,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlvertexstepfunction>
|
||||
#[repr(u64)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub enum MTLVertexStepFunction {
|
||||
Constant = 0,
|
||||
PerVertex = 1,
|
||||
PerInstance = 2,
|
||||
PerPatch = 3,
|
||||
PerPatchControlPoint = 4,
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlvertexbufferlayoutdescriptor>
|
||||
pub enum MTLVertexBufferLayoutDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLVertexBufferLayoutDescriptor;
|
||||
pub struct VertexBufferLayoutDescriptor;
|
||||
}
|
||||
|
||||
impl VertexBufferLayoutDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLVertexBufferLayoutDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VertexBufferLayoutDescriptorRef {
|
||||
pub fn stride(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, stride] }
|
||||
}
|
||||
|
||||
pub fn set_stride(&self, stride: NSUInteger) {
|
||||
unsafe { msg_send![self, setStride: stride] }
|
||||
}
|
||||
|
||||
pub fn step_function(&self) -> MTLVertexStepFunction {
|
||||
unsafe { msg_send![self, stepFunction] }
|
||||
}
|
||||
|
||||
pub fn set_step_function(&self, func: MTLVertexStepFunction) {
|
||||
unsafe { msg_send![self, setStepFunction: func] }
|
||||
}
|
||||
|
||||
pub fn step_rate(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, stepRate] }
|
||||
}
|
||||
|
||||
pub fn set_step_rate(&self, step_rate: NSUInteger) {
|
||||
unsafe { msg_send![self, setStepRate: step_rate] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlvertexbufferlayoutdescriptorarray>
|
||||
pub enum MTLVertexBufferLayoutDescriptorArray {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLVertexBufferLayoutDescriptorArray;
|
||||
pub struct VertexBufferLayoutDescriptorArray;
|
||||
}
|
||||
|
||||
impl VertexBufferLayoutDescriptorArrayRef {
|
||||
pub fn object_at(&self, index: NSUInteger) -> Option<&VertexBufferLayoutDescriptorRef> {
|
||||
unsafe { msg_send![self, objectAtIndexedSubscript: index] }
|
||||
}
|
||||
|
||||
pub fn set_object_at(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
layout: Option<&VertexBufferLayoutDescriptorRef>,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self, setObject:layout
|
||||
atIndexedSubscript:index]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlvertexattributedescriptor>
|
||||
pub enum MTLVertexAttributeDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLVertexAttributeDescriptor;
|
||||
pub struct VertexAttributeDescriptor;
|
||||
}
|
||||
|
||||
impl VertexAttributeDescriptor {
|
||||
pub fn new() -> Self {
|
||||
unsafe {
|
||||
let class = class!(MTLVertexAttributeDescriptor);
|
||||
msg_send![class, new]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VertexAttributeDescriptorRef {
|
||||
pub fn format(&self) -> MTLVertexFormat {
|
||||
unsafe { msg_send![self, format] }
|
||||
}
|
||||
|
||||
pub fn set_format(&self, format: MTLVertexFormat) {
|
||||
unsafe { msg_send![self, setFormat: format] }
|
||||
}
|
||||
|
||||
pub fn offset(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, offset] }
|
||||
}
|
||||
|
||||
pub fn set_offset(&self, offset: NSUInteger) {
|
||||
unsafe { msg_send![self, setOffset: offset] }
|
||||
}
|
||||
|
||||
pub fn buffer_index(&self) -> NSUInteger {
|
||||
unsafe { msg_send![self, bufferIndex] }
|
||||
}
|
||||
|
||||
pub fn set_buffer_index(&self, index: NSUInteger) {
|
||||
unsafe { msg_send![self, setBufferIndex: index] }
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlvertexattributedescriptorarray>
|
||||
pub enum MTLVertexAttributeDescriptorArray {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLVertexAttributeDescriptorArray;
|
||||
pub struct VertexAttributeDescriptorArray;
|
||||
}
|
||||
|
||||
impl VertexAttributeDescriptorArrayRef {
|
||||
pub fn object_at(&self, index: NSUInteger) -> Option<&VertexAttributeDescriptorRef> {
|
||||
unsafe { msg_send![self, objectAtIndexedSubscript: index] }
|
||||
}
|
||||
|
||||
pub fn set_object_at(
|
||||
&self,
|
||||
index: NSUInteger,
|
||||
attribute: Option<&VertexAttributeDescriptorRef>,
|
||||
) {
|
||||
unsafe {
|
||||
msg_send![self, setObject:attribute
|
||||
atIndexedSubscript:index]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://developer.apple.com/documentation/metal/mtlvertexdescriptor>
|
||||
pub enum MTLVertexDescriptor {}
|
||||
|
||||
foreign_obj_type! {
|
||||
type CType = MTLVertexDescriptor;
|
||||
pub struct VertexDescriptor;
|
||||
}
|
||||
|
||||
impl VertexDescriptor {
|
||||
pub fn new<'a>() -> &'a VertexDescriptorRef {
|
||||
unsafe {
|
||||
let class = class!(MTLVertexDescriptor);
|
||||
msg_send![class, vertexDescriptor]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VertexDescriptorRef {
|
||||
pub fn layouts(&self) -> &VertexBufferLayoutDescriptorArrayRef {
|
||||
unsafe { msg_send![self, layouts] }
|
||||
}
|
||||
|
||||
pub fn attributes(&self) -> &VertexAttributeDescriptorArrayRef {
|
||||
unsafe { msg_send![self, attributes] }
|
||||
}
|
||||
|
||||
#[cfg(feature = "private")]
|
||||
pub unsafe fn serialize_descriptor(&self) -> *mut std::ffi::c_void {
|
||||
msg_send![self, newSerializedDescriptor]
|
||||
}
|
||||
|
||||
pub fn reset(&self) {
|
||||
unsafe { msg_send![self, reset] }
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue