Bug 1622846 - Update BlendFactor API in WebGPU r=webidl,jimb,smaug

This is another incremental update of wgpu and WebGPU APIs.
It increases stability and makes us run most of the Austin's samples (again).
Likely fixes https://bugzilla.mozilla.org/show_bug.cgi?id=1704148

Differential Revision: https://phabricator.services.mozilla.com/D112828
This commit is contained in:
Dzmitry Malyshau 2021-04-22 19:18:49 +00:00
Родитель 274b1a8f6e
Коммит cdb4fe1fcb
321 изменённых файлов: 6668 добавлений и 3955 удалений

Просмотреть файл

@ -105,17 +105,17 @@ rev = "39f95e2f7cd6e632a379cdeee62c68e8cedd7810"
[source."https://github.com/gfx-rs/naga"]
git = "https://github.com/gfx-rs/naga"
replace-with = "vendored-sources"
tag = "gfx-20"
tag = "gfx-22"
[source."https://github.com/gfx-rs/metal-rs"]
git = "https://github.com/gfx-rs/metal-rs"
replace-with = "vendored-sources"
rev = "439c986eb7a9b91e88b61def2daa66e4043fcbef"
rev = "78f632d194c7c16d18b71d7373c4080847d110b0"
[source."https://github.com/gfx-rs/gfx"]
git = "https://github.com/gfx-rs/gfx"
replace-with = "vendored-sources"
rev = "3ee1ca9ba486b166a52765024d8d149cbb28d486"
rev = "84e02f96149207b1bafecb1924b14315930c98ee"
[source."https://github.com/gfx-rs/d3d12-rs"]
git = "https://github.com/gfx-rs/d3d12-rs"

21
Cargo.lock сгенерированный
Просмотреть файл

@ -1846,7 +1846,7 @@ dependencies = [
[[package]]
name = "gfx-auxil"
version = "0.8.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"fxhash",
"gfx-hal",
@ -1856,7 +1856,7 @@ dependencies = [
[[package]]
name = "gfx-backend-dx11"
version = "0.7.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"arrayvec",
"bitflags",
@ -1877,7 +1877,7 @@ dependencies = [
[[package]]
name = "gfx-backend-dx12"
version = "0.7.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"arrayvec",
"bit-set",
@ -1898,7 +1898,7 @@ dependencies = [
[[package]]
name = "gfx-backend-empty"
version = "0.7.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"gfx-hal",
"log",
@ -1908,7 +1908,7 @@ dependencies = [
[[package]]
name = "gfx-backend-metal"
version = "0.7.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"arrayvec",
"bitflags",
@ -1924,6 +1924,7 @@ dependencies = [
"naga",
"objc",
"parking_lot",
"profiling",
"range-alloc",
"raw-window-handle",
"spirv_cross",
@ -1933,7 +1934,7 @@ dependencies = [
[[package]]
name = "gfx-backend-vulkan"
version = "0.7.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"arrayvec",
"ash",
@ -1953,7 +1954,7 @@ dependencies = [
[[package]]
name = "gfx-hal"
version = "0.7.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"bitflags",
"naga",
@ -3060,7 +3061,7 @@ dependencies = [
[[package]]
name = "metal"
version = "0.21.0"
source = "git+https://github.com/gfx-rs/metal-rs?rev=439c986eb7a9b91e88b61def2daa66e4043fcbef#439c986eb7a9b91e88b61def2daa66e4043fcbef"
source = "git+https://github.com/gfx-rs/metal-rs?rev=78f632d194c7c16d18b71d7373c4080847d110b0#78f632d194c7c16d18b71d7373c4080847d110b0"
dependencies = [
"bitflags",
"block",
@ -3347,7 +3348,7 @@ checksum = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"
[[package]]
name = "naga"
version = "0.3.1"
source = "git+https://github.com/gfx-rs/naga?tag=gfx-20#0369ee181ed9cd315635fc0e3d99deecdbc72246"
source = "git+https://github.com/gfx-rs/naga?tag=gfx-22#9cd6fd9c205a57824644d0baedc6c15997be1e36"
dependencies = [
"bit-set",
"bitflags",
@ -4186,7 +4187,7 @@ dependencies = [
[[package]]
name = "range-alloc"
version = "0.1.2"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
[[package]]
name = "raw-cpuid"

Просмотреть файл

@ -234,11 +234,11 @@ void RenderPassEncoder::SetScissorRect(uint32_t x, uint32_t y, uint32_t width,
}
}
void RenderPassEncoder::SetBlendColor(
void RenderPassEncoder::SetBlendConstant(
const dom::DoubleSequenceOrGPUColorDict& color) {
if (mValid) {
ffi::WGPUColor aColor = ConvertColor(color.GetAsGPUColorDict());
ffi::wgpu_render_pass_set_blend_color(mPass, &aColor);
ffi::wgpu_render_pass_set_blend_constant(mPass, &aColor);
}
}

Просмотреть файл

@ -81,7 +81,7 @@ class RenderPassEncoder final : public ObjectBase,
void SetViewport(float x, float y, float width, float height, float minDepth,
float maxDepth);
void SetScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
void SetBlendColor(const dom::DoubleSequenceOrGPUColorDict& color);
void SetBlendConstant(const dom::DoubleSequenceOrGPUColorDict& color);
void SetStencilReference(uint32_t reference);
void EndPass(ErrorResult& aRv);
};

Просмотреть файл

@ -696,16 +696,9 @@ ipc::IPCResult WebGPUParent::RecvShutdown() {
ipc::IPCResult WebGPUParent::RecvDeviceAction(RawId aSelf,
const ipc::ByteBuf& aByteBuf) {
ipc::ByteBuf byteBuf;
ErrorBuffer error;
ffi::wgpu_server_device_action(mContext, aSelf, ToFFI(&aByteBuf),
ToFFI(&byteBuf), error.ToFFI());
if (byteBuf.mData) {
if (!SendDropAction(std::move(byteBuf))) {
NS_WARNING("Unable to set a drop action!");
}
}
error.ToFFI());
error.CheckAndForward(this, aSelf);
return IPC_OK();

Просмотреть файл

@ -8,7 +8,6 @@
*/
typedef [EnforceRange] unsigned long GPUBufferDynamicOffset;
typedef [EnforceRange] unsigned long GPUStencilValue;
typedef [EnforceRange] unsigned long GPUSampleMask;
@ -755,17 +754,17 @@ dictionary GPUMultisampleState {
enum GPUBlendFactor {
"zero",
"one",
"src-color",
"one-minus-src-color",
"src",
"one-minus-src",
"src-alpha",
"one-minus-src-alpha",
"dst-color",
"one-minus-dst-color",
"dst",
"one-minus-dst",
"dst-alpha",
"one-minus-dst-alpha",
"src-alpha-saturated",
"blend-color",
"one-minus-blend-color",
"constant",
"one-minus-constant",
};
enum GPUBlendOperation {
@ -1009,7 +1008,7 @@ interface GPURenderPassEncoder {
void setScissorRect(GPUIntegerCoordinate x, GPUIntegerCoordinate y,
GPUIntegerCoordinate width, GPUIntegerCoordinate height);
void setBlendColor(GPUColor color);
void setBlendConstant(GPUColor color);
void setStencilReference(GPUStencilValue reference);
//void beginOcclusionQuery(GPUSize32 queryIndex);
@ -1155,6 +1154,12 @@ dictionary GPUSwapChainDescriptor : GPUObjectDescriptorBase {
required GPUDevice device;
required GPUTextureFormat format;
GPUTextureUsageFlags usage = 0x10; //GPUTextureUsage.OUTPUT_ATTACHMENT
GPUCanvasCompositingAlphaMode compositingAlphaMode = "opaque";
};
enum GPUCanvasCompositingAlphaMode {
"opaque",
"premultiplied",
};
[Pref="dom.webgpu.enabled",

21
gfx/wgpu/Cargo.lock сгенерированный
Просмотреть файл

@ -465,7 +465,7 @@ dependencies = [
[[package]]
name = "gfx-auxil"
version = "0.8.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"fxhash",
"gfx-hal",
@ -475,7 +475,7 @@ dependencies = [
[[package]]
name = "gfx-backend-dx11"
version = "0.7.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"arrayvec",
"bitflags",
@ -496,7 +496,7 @@ dependencies = [
[[package]]
name = "gfx-backend-dx12"
version = "0.7.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"arrayvec",
"bit-set",
@ -517,7 +517,7 @@ dependencies = [
[[package]]
name = "gfx-backend-empty"
version = "0.7.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"gfx-hal",
"log",
@ -527,7 +527,7 @@ dependencies = [
[[package]]
name = "gfx-backend-metal"
version = "0.7.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"arrayvec",
"bitflags",
@ -543,6 +543,7 @@ dependencies = [
"naga",
"objc",
"parking_lot",
"profiling",
"range-alloc",
"raw-window-handle",
"spirv_cross",
@ -552,7 +553,7 @@ dependencies = [
[[package]]
name = "gfx-backend-vulkan"
version = "0.7.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"arrayvec",
"ash",
@ -572,7 +573,7 @@ dependencies = [
[[package]]
name = "gfx-hal"
version = "0.7.0"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
dependencies = [
"bitflags",
"naga",
@ -815,7 +816,7 @@ dependencies = [
[[package]]
name = "metal"
version = "0.21.0"
source = "git+https://github.com/gfx-rs/metal-rs?rev=439c986eb7a9b91e88b61def2daa66e4043fcbef#439c986eb7a9b91e88b61def2daa66e4043fcbef"
source = "git+https://github.com/gfx-rs/metal-rs?rev=78f632d194c7c16d18b71d7373c4080847d110b0#78f632d194c7c16d18b71d7373c4080847d110b0"
dependencies = [
"bitflags",
"block",
@ -871,7 +872,7 @@ dependencies = [
[[package]]
name = "naga"
version = "0.3.1"
source = "git+https://github.com/gfx-rs/naga?tag=gfx-20#0369ee181ed9cd315635fc0e3d99deecdbc72246"
source = "git+https://github.com/gfx-rs/naga?tag=gfx-22#9cd6fd9c205a57824644d0baedc6c15997be1e36"
dependencies = [
"bit-set",
"bitflags",
@ -1126,7 +1127,7 @@ dependencies = [
[[package]]
name = "range-alloc"
version = "0.1.2"
source = "git+https://github.com/gfx-rs/gfx?rev=3ee1ca9ba486b166a52765024d8d149cbb28d486#3ee1ca9ba486b166a52765024d8d149cbb28d486"
source = "git+https://github.com/gfx-rs/gfx?rev=84e02f96149207b1bafecb1924b14315930c98ee#84e02f96149207b1bafecb1924b14315930c98ee"
[[package]]
name = "raw-window-handle"

Просмотреть файл

@ -265,7 +265,7 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
root_id: ic.root_id,
group_ids: &ic.group_ids,
});
let (_, _, error) =
let (_, error) =
self.device_create_compute_pipeline::<B>(device, &desc, id, implicit_ids);
if let Some(e) = error {
panic!("{:?}", e);
@ -287,7 +287,7 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
root_id: ic.root_id,
group_ids: &ic.group_ids,
});
let (_, _, error) =
let (_, error) =
self.device_create_render_pipeline::<B>(device, &desc, id, implicit_ids);
if let Some(e) = error {
panic!("{:?}", e);

Просмотреть файл

@ -1,9 +1,9 @@
[[stage(vertex)]]
fn vs_main([[builtin(vertex_index)]] vertex_index: u32) -> [[builtin(position)]] vec4<f32> {
// hacky way to draw a large triangle
const tmp1 = i32(vertex_index) / 2;
const tmp2 = i32(vertex_index) & 1;
const pos = vec2<f32>(
let tmp1 = i32(vertex_index) / 2;
let tmp2 = i32(vertex_index) & 1;
let pos = vec2<f32>(
f32(tmp1) * 4.0 - 1.0,
f32(tmp2) * 4.0 - 1.0
);

Просмотреть файл

@ -40,28 +40,28 @@ thiserror = "1"
gpu-alloc = { git = "https://github.com/zakarumych/gpu-alloc.git", rev = "2cd1ad650cdd24d1647b6041f77ced0cbf1ff2a6" }
gpu-descriptor = { version = "0.1" }
hal = { package = "gfx-hal", git = "https://github.com/gfx-rs/gfx", rev = "3ee1ca9ba486b166a52765024d8d149cbb28d486" }
gfx-backend-empty = { git = "https://github.com/gfx-rs/gfx", rev = "3ee1ca9ba486b166a52765024d8d149cbb28d486" }
hal = { package = "gfx-hal", git = "https://github.com/gfx-rs/gfx", rev = "84e02f96149207b1bafecb1924b14315930c98ee" }
gfx-backend-empty = { git = "https://github.com/gfx-rs/gfx", rev = "84e02f96149207b1bafecb1924b14315930c98ee" }
[target.'cfg(all(not(target_arch = "wasm32"), all(unix, not(target_os = "ios"), not(target_os = "macos"))))'.dependencies]
gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "3ee1ca9ba486b166a52765024d8d149cbb28d486", features = ["naga"] }
#gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx", rev = "3ee1ca9ba486b166a52765024d8d149cbb28d486" }
gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "84e02f96149207b1bafecb1924b14315930c98ee", features = ["naga"] }
#gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx", rev = "84e02f96149207b1bafecb1924b14315930c98ee" }
[target.'cfg(all(not(target_arch = "wasm32"), any(target_os = "ios", target_os = "macos")))'.dependencies]
gfx-backend-metal = { git = "https://github.com/gfx-rs/gfx", rev = "3ee1ca9ba486b166a52765024d8d149cbb28d486" }
gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "3ee1ca9ba486b166a52765024d8d149cbb28d486", optional = true }
gfx-backend-metal = { git = "https://github.com/gfx-rs/gfx", rev = "84e02f96149207b1bafecb1924b14315930c98ee" }
gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "84e02f96149207b1bafecb1924b14315930c98ee", optional = true }
[target.'cfg(all(not(target_arch = "wasm32"), windows))'.dependencies]
gfx-backend-dx12 = { git = "https://github.com/gfx-rs/gfx", rev = "3ee1ca9ba486b166a52765024d8d149cbb28d486" }
gfx-backend-dx11 = { git = "https://github.com/gfx-rs/gfx", rev = "3ee1ca9ba486b166a52765024d8d149cbb28d486" }
gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "3ee1ca9ba486b166a52765024d8d149cbb28d486", features = ["naga"] }
gfx-backend-dx12 = { git = "https://github.com/gfx-rs/gfx", rev = "84e02f96149207b1bafecb1924b14315930c98ee" }
gfx-backend-dx11 = { git = "https://github.com/gfx-rs/gfx", rev = "84e02f96149207b1bafecb1924b14315930c98ee" }
gfx-backend-vulkan = { git = "https://github.com/gfx-rs/gfx", rev = "84e02f96149207b1bafecb1924b14315930c98ee", features = ["naga"] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
#gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx", rev = "3ee1ca9ba486b166a52765024d8d149cbb28d486" }
#gfx-backend-gl = { git = "https://github.com/gfx-rs/gfx", rev = "84e02f96149207b1bafecb1924b14315930c98ee" }
[dependencies.naga]
git = "https://github.com/gfx-rs/naga"
tag = "gfx-20"
tag = "gfx-22"
features = ["spv-in", "spv-out", "wgsl-in"]
[dependencies.wgt]

Просмотреть файл

@ -10,7 +10,7 @@ use crate::{
hub::Resource,
id::{BindGroupLayoutId, BufferId, DeviceId, SamplerId, TextureViewId, Valid},
memory_init_tracker::MemoryInitTrackerAction,
track::{TrackerSet, DUMMY_SELECTOR},
track::{TrackerSet, UsageConflict, DUMMY_SELECTOR},
validation::{MissingBufferUsageError, MissingTextureUsageError},
FastHashMap, Label, LifeGuard, MultiRefCount, Stored, MAX_BIND_GROUPS,
};
@ -43,6 +43,8 @@ pub enum CreateBindGroupLayoutError {
TooManyBindings(BindingTypeMaxCountError),
}
//TODO: refactor this to move out `enum BindingError`.
#[derive(Clone, Debug, Error)]
pub enum CreateBindGroupError {
#[error(transparent)]
@ -130,12 +132,24 @@ pub enum CreateBindGroupError {
layout_format: wgt::TextureFormat,
view_format: wgt::TextureFormat,
},
#[error("the given sampler is/is not a comparison sampler, while the layout type indicates otherwise")]
WrongSamplerComparison,
#[error("sampler binding {binding} expects comparison = {layout_cmp}, but given a sampler with comparison = {sampler_cmp}")]
WrongSamplerComparison {
binding: u32,
layout_cmp: bool,
sampler_cmp: bool,
},
#[error("sampler binding {binding} expects filtering = {layout_flt}, but given a sampler with filtering = {sampler_flt}")]
WrongSamplerFiltering {
binding: u32,
layout_flt: bool,
sampler_flt: bool,
},
#[error("bound texture views can not have both depth and stencil aspects enabled")]
DepthStencilAspect,
#[error("the adapter does not support simultaneous read + write storage texture access for the format {0:?}")]
StorageReadWriteNotSupported(wgt::TextureFormat),
#[error(transparent)]
ResourceUsageConflict(#[from] UsageConflict),
}
#[derive(Clone, Debug, Error)]

Просмотреть файл

@ -478,7 +478,7 @@ impl RenderBundleEncoder {
| RenderCommand::BeginPipelineStatisticsQuery { .. }
| RenderCommand::EndPipelineStatisticsQuery => unimplemented!(),
RenderCommand::ExecuteBundle(_)
| RenderCommand::SetBlendColor(_)
| RenderCommand::SetBlendConstant(_)
| RenderCommand::SetStencilReference(_)
| RenderCommand::SetViewport { .. }
| RenderCommand::SetScissor(_) => unreachable!("not supported by a render bundle"),
@ -533,6 +533,8 @@ pub enum CreateRenderBundleError {
pub enum ExecutionError {
#[error("buffer {0:?} is destroyed")]
DestroyedBuffer(id::BufferId),
#[error("using {0} in a render bundle is not implemented")]
Unimplemented(&'static str),
}
pub type RenderBundleDescriptor<'a> = wgt::RenderBundleDescriptor<Label<'a>>;
@ -733,15 +735,21 @@ impl RenderBundle {
cmd_buf.draw_indexed_indirect(buffer, offset, 1, 0);
}
RenderCommand::MultiDrawIndirect { .. }
| RenderCommand::MultiDrawIndirectCount { .. } => unimplemented!(),
RenderCommand::PushDebugGroup { color: _, len: _ } => unimplemented!(),
RenderCommand::InsertDebugMarker { color: _, len: _ } => unimplemented!(),
RenderCommand::PopDebugGroup => unimplemented!(),
| RenderCommand::MultiDrawIndirectCount { .. } => {
return Err(ExecutionError::Unimplemented("multi-draw-indirect"))
}
RenderCommand::PushDebugGroup { .. }
| RenderCommand::InsertDebugMarker { .. }
| RenderCommand::PopDebugGroup => {
return Err(ExecutionError::Unimplemented("debug-markers"))
}
RenderCommand::WriteTimestamp { .. }
| RenderCommand::BeginPipelineStatisticsQuery { .. }
| RenderCommand::EndPipelineStatisticsQuery => unimplemented!(),
| RenderCommand::EndPipelineStatisticsQuery => {
return Err(ExecutionError::Unimplemented("queries"))
}
RenderCommand::ExecuteBundle(_)
| RenderCommand::SetBlendColor(_)
| RenderCommand::SetBlendConstant(_)
| RenderCommand::SetStencilReference(_)
| RenderCommand::SetViewport { .. }
| RenderCommand::SetScissor(_) => unreachable!(),

Просмотреть файл

@ -22,8 +22,8 @@ pub type BufferError = UseExtendError<BufferUse>;
/// Error validating a draw call.
#[derive(Clone, Debug, Error, PartialEq)]
pub enum DrawError {
#[error("blend color needs to be set")]
MissingBlendColor,
#[error("blend constant needs to be set")]
MissingBlendConstant,
#[error("render pipeline must be set")]
MissingPipeline,
#[error("vertex buffer {index} must be set")]
@ -95,6 +95,8 @@ pub enum RenderCommandError {
InvalidViewport,
#[error("Invalid ScissorRect parameters")]
InvalidScissorRect,
#[error("Support for {0} is not implemented yet")]
Unimplemented(&'static str),
}
#[derive(Clone, Copy, Debug, Default)]
@ -142,7 +144,7 @@ pub enum RenderCommand {
offset: BufferAddress,
size: Option<BufferSize>,
},
SetBlendColor(Color),
SetBlendConstant(Color),
SetStencilReference(u32),
SetViewport {
rect: Rect<f32>,

Просмотреть файл

@ -326,7 +326,7 @@ impl VertexState {
struct State {
pipeline_flags: PipelineFlags,
binder: Binder,
blend_color: OptionalState,
blend_constant: OptionalState,
stencil_reference: u32,
pipeline: StateChange<id::RenderPipelineId>,
index: IndexState,
@ -355,8 +355,8 @@ impl State {
if self.pipeline.is_unset() {
return Err(DrawError::MissingPipeline);
}
if self.blend_color == OptionalState::Required {
return Err(DrawError::MissingBlendColor);
if self.blend_constant == OptionalState::Required {
return Err(DrawError::MissingBlendConstant);
}
if indexed {
// Pipeline expects an index buffer
@ -972,7 +972,7 @@ impl<'a, B: GfxBackend> RenderPassInfo<'a, B> {
ra.selector.clone(),
ra.new_use,
)
.unwrap();
.map_err(UsageConflict::from)?;
if let Some(usage) = ra.previous_use {
// Make the attachment tracks to be aware of the internal
@ -1068,7 +1068,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let mut state = State {
pipeline_flags: PipelineFlags::empty(),
binder: Binder::new(),
blend_color: OptionalState::Unused,
blend_constant: OptionalState::Unused,
stencil_reference: 0,
pipeline: StateChange::new(),
index: IndexState::default(),
@ -1109,7 +1109,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.trackers
.bind_groups
.use_extend(&*bind_group_guard, bind_group_id, (), ())
.unwrap();
.map_err(|_| RenderCommandError::InvalidBindGroup(bind_group_id))
.map_pass_err(scope)?;
bind_group
.validate_dynamic_bindings(&temp_offsets)
.map_pass_err(scope)?;
@ -1188,8 +1189,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}
state
.blend_color
.require(pipeline.flags.contains(PipelineFlags::BLEND_COLOR));
.blend_constant
.require(pipeline.flags.contains(PipelineFlags::BLEND_CONSTANT));
unsafe {
raw.bind_graphics_pipeline(&pipeline.raw);
@ -1377,8 +1378,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}
state.vertex.update_limits();
}
RenderCommand::SetBlendColor(ref color) => {
state.blend_color = OptionalState::Set;
RenderCommand::SetBlendConstant(ref color) => {
state.blend_constant = OptionalState::Set;
unsafe {
raw.set_blend_constants(conv::map_color_f32(color));
}
@ -1911,6 +1912,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
ExecutionError::DestroyedBuffer(id) => {
RenderCommandError::DestroyedBuffer(id)
}
ExecutionError::Unimplemented(what) => {
RenderCommandError::Unimplemented(what)
}
})
.map_pass_err(scope)?;
@ -2036,10 +2040,10 @@ pub mod render_ffi {
}
#[no_mangle]
pub extern "C" fn wgpu_render_pass_set_blend_color(pass: &mut RenderPass, color: &Color) {
pub extern "C" fn wgpu_render_pass_set_blend_constant(pass: &mut RenderPass, color: &Color) {
pass.base
.commands
.push(RenderCommand::SetBlendColor(*color));
.push(RenderCommand::SetBlendConstant(*color));
}
#[no_mangle]

Просмотреть файл

@ -4,6 +4,7 @@
use crate::{
command::{LoadOp, PassChannel, StoreOp},
pipeline::ColorStateError,
resource, PrivateFeatures,
};
@ -196,16 +197,24 @@ pub fn map_primitive_topology(primitive_topology: wgt::PrimitiveTopology) -> hal
}
}
pub fn map_color_target_state(desc: &wgt::ColorTargetState) -> hal::pso::ColorBlendDesc {
pub fn map_color_target_state(
desc: &wgt::ColorTargetState,
) -> Result<hal::pso::ColorBlendDesc, ColorStateError> {
let color_mask = desc.write_mask;
let blend = desc.blend.as_ref().map(|bs| hal::pso::BlendState {
color: map_blend_component(&bs.color),
alpha: map_blend_component(&bs.alpha),
});
hal::pso::ColorBlendDesc {
let blend = desc
.blend
.as_ref()
.map(|bs| {
Ok(hal::pso::BlendState {
color: map_blend_component(&bs.color)?,
alpha: map_blend_component(&bs.alpha)?,
})
})
.transpose()?;
Ok(hal::pso::ColorBlendDesc {
mask: map_color_write_flags(color_mask),
blend,
}
})
}
fn map_color_write_flags(flags: wgt::ColorWrite) -> hal::pso::ColorMask {
@ -228,25 +237,48 @@ fn map_color_write_flags(flags: wgt::ColorWrite) -> hal::pso::ColorMask {
value
}
fn map_blend_component(component: &wgt::BlendComponent) -> hal::pso::BlendOp {
fn map_blend_component(
component: &wgt::BlendComponent,
) -> Result<hal::pso::BlendOp, ColorStateError> {
use hal::pso::BlendOp as H;
use wgt::BlendOperation as Bo;
match component.operation {
Bo::Add => H::Add {
src: map_blend_factor(component.src_factor),
dst: map_blend_factor(component.dst_factor),
Ok(match *component {
wgt::BlendComponent {
operation: Bo::Add,
src_factor,
dst_factor,
} => H::Add {
src: map_blend_factor(src_factor),
dst: map_blend_factor(dst_factor),
},
Bo::Subtract => H::Sub {
src: map_blend_factor(component.src_factor),
dst: map_blend_factor(component.dst_factor),
wgt::BlendComponent {
operation: Bo::Subtract,
src_factor,
dst_factor,
} => H::Sub {
src: map_blend_factor(src_factor),
dst: map_blend_factor(dst_factor),
},
Bo::ReverseSubtract => H::RevSub {
src: map_blend_factor(component.src_factor),
dst: map_blend_factor(component.dst_factor),
wgt::BlendComponent {
operation: Bo::ReverseSubtract,
src_factor,
dst_factor,
} => H::RevSub {
src: map_blend_factor(src_factor),
dst: map_blend_factor(dst_factor),
},
Bo::Min => H::Min,
Bo::Max => H::Max,
}
wgt::BlendComponent {
operation: Bo::Min,
src_factor: wgt::BlendFactor::One,
dst_factor: wgt::BlendFactor::One,
} => H::Min,
wgt::BlendComponent {
operation: Bo::Max,
src_factor: wgt::BlendFactor::One,
dst_factor: wgt::BlendFactor::One,
} => H::Max,
_ => return Err(ColorStateError::InvalidMinMaxBlendFactors(*component)),
})
}
fn map_blend_factor(blend_factor: wgt::BlendFactor) -> hal::pso::Factor {
@ -255,17 +287,17 @@ fn map_blend_factor(blend_factor: wgt::BlendFactor) -> hal::pso::Factor {
match blend_factor {
Bf::Zero => H::Zero,
Bf::One => H::One,
Bf::SrcColor => H::SrcColor,
Bf::OneMinusSrcColor => H::OneMinusSrcColor,
Bf::Src => H::SrcColor,
Bf::OneMinusSrc => H::OneMinusSrcColor,
Bf::SrcAlpha => H::SrcAlpha,
Bf::OneMinusSrcAlpha => H::OneMinusSrcAlpha,
Bf::DstColor => H::DstColor,
Bf::OneMinusDstColor => H::OneMinusDstColor,
Bf::Dst => H::DstColor,
Bf::OneMinusDst => H::OneMinusDstColor,
Bf::DstAlpha => H::DstAlpha,
Bf::OneMinusDstAlpha => H::OneMinusDstAlpha,
Bf::SrcAlphaSaturated => H::SrcAlphaSaturate,
Bf::BlendColor => H::ConstColor,
Bf::OneMinusBlendColor => H::OneMinusConstColor,
Bf::Constant => H::ConstColor,
Bf::OneMinusConstant => H::OneMinusConstColor,
}
}

Просмотреть файл

@ -11,7 +11,7 @@ use crate::{
id, instance,
memory_init_tracker::{MemoryInitKind, MemoryInitTracker, MemoryInitTrackerAction},
pipeline, resource, swap_chain,
track::{BufferState, TextureSelector, TextureState, TrackerSet},
track::{BufferState, TextureSelector, TextureState, TrackerSet, UsageConflict},
validation::{self, check_buffer_usage, check_texture_usage},
FastHashMap, Label, LabelHelpers, LifeGuard, MultiRefCount, PrivateFeatures, Stored,
SubmissionIndex, MAX_BIND_GROUPS,
@ -56,6 +56,8 @@ pub const MAX_VERTEX_BUFFERS: usize = 16;
pub const MAX_ANISOTROPY: u8 = 16;
pub const SHADER_STAGE_COUNT: usize = 3;
const IMPLICIT_FAILURE: &str = "failed implicit";
pub type DeviceDescriptor<'a> = wgt::DeviceDescriptor<Label<'a>>;
pub fn all_buffer_stages() -> hal::pso::PipelineStage {
@ -864,6 +866,8 @@ impl<B: GfxBackend> Device<B> {
conv::map_texture_view_dimension(view_dim),
conv::map_texture_format(format, self.private_features),
hal::format::Swizzle::NO,
// conservatively assume the same usage
conv::map_texture_usage(texture.usage, aspects),
range,
)
.or(Err(resource::CreateTextureViewError::OutOfMemory))?
@ -940,10 +944,14 @@ impl<B: GfxBackend> Device<B> {
Some(wgt::SamplerBorderColor::OpaqueWhite) => hal::image::BorderColor::OpaqueWhite,
};
let filtering = [desc.min_filter, desc.mag_filter, desc.mipmap_filter]
.contains(&wgt::FilterMode::Linear);
let info = hal::image::SamplerDesc {
min_filter: conv::map_filter(desc.min_filter),
mag_filter: conv::map_filter(desc.mag_filter),
mip_filter: conv::map_filter(desc.mipmap_filter),
reduction_mode: hal::image::ReductionMode::WeightedAverage,
wrap_mode: (
conv::map_wrap(desc.address_modes[0]),
conv::map_wrap(desc.address_modes[1]),
@ -975,6 +983,7 @@ impl<B: GfxBackend> Device<B> {
},
life_guard: LifeGuard::new(desc.label.borrow_or_default()),
comparison: info.comparison.is_some(),
filtering,
})
}
@ -1412,7 +1421,7 @@ impl<B: GfxBackend> Device<B> {
Br::Sampler(id) => {
match decl.ty {
wgt::BindingType::Sampler {
filtering: _,
filtering,
comparison,
} => {
let sampler = used
@ -1422,7 +1431,19 @@ impl<B: GfxBackend> Device<B> {
// Check the actual sampler to also (not) be a comparison sampler
if sampler.comparison != comparison {
return Err(Error::WrongSamplerComparison);
return Err(Error::WrongSamplerComparison {
binding,
layout_cmp: comparison,
sampler_cmp: sampler.comparison,
});
}
// Check the actual sampler to be non-filtering, if required
if sampler.filtering && !filtering {
return Err(Error::WrongSamplerFiltering {
binding,
layout_flt: filtering,
sampler_flt: sampler.filtering,
});
}
SmallVec::from([hal::pso::Descriptor::Sampler(&sampler.raw)])
@ -1559,7 +1580,7 @@ impl<B: GfxBackend> Device<B> {
view.selector.clone(),
internal_use,
)
.unwrap();
.map_err(UsageConflict::from)?;
check_texture_usage(texture.usage, pub_usage)?;
let image_layout =
conv::map_texture_state(internal_use, view.aspects).1;
@ -1623,7 +1644,7 @@ impl<B: GfxBackend> Device<B> {
view.selector.clone(),
internal_use,
)
.unwrap();
.map_err(UsageConflict::from)?;
check_texture_usage(texture.usage, pub_usage)?;
let image_layout =
conv::map_texture_state(internal_use, view.aspects).1;
@ -1800,13 +1821,7 @@ impl<B: GfxBackend> Device<B> {
mut derived_group_layouts: ArrayVec<[binding_model::BindEntryMap; MAX_BIND_GROUPS]>,
bgl_guard: &mut Storage<binding_model::BindGroupLayout<B>, id::BindGroupLayoutId>,
pipeline_layout_guard: &mut Storage<binding_model::PipelineLayout<B>, id::PipelineLayoutId>,
) -> Result<
(id::PipelineLayoutId, pipeline::ImplicitBindGroupCount),
pipeline::ImplicitLayoutError,
> {
let derived_bind_group_count =
derived_group_layouts.len() as pipeline::ImplicitBindGroupCount;
) -> Result<id::PipelineLayoutId, pipeline::ImplicitLayoutError> {
while derived_group_layouts
.last()
.map_or(false, |map| map.is_empty())
@ -1821,9 +1836,7 @@ impl<B: GfxBackend> Device<B> {
ids.group_ids.len(),
derived_group_layouts.len()
);
return Err(pipeline::ImplicitLayoutError::MissingIds(
derived_bind_group_count,
));
return Err(pipeline::ImplicitLayoutError::MissingIds(group_count as _));
}
for (bgl_id, map) in ids.group_ids.iter_mut().zip(derived_group_layouts) {
@ -1833,7 +1846,7 @@ impl<B: GfxBackend> Device<B> {
}
None => {
let bgl = self.create_bind_group_layout(self_id, None, map)?;
bgl_guard.insert(*bgl_id, bgl);
bgl_guard.force_replace(*bgl_id, bgl);
}
};
}
@ -1844,8 +1857,8 @@ impl<B: GfxBackend> Device<B> {
push_constant_ranges: Cow::Borrowed(&[]), //TODO?
};
let layout = self.create_pipeline_layout(self_id, &layout_desc, bgl_guard)?;
pipeline_layout_guard.insert(ids.root_id, layout);
Ok((ids.root_id, derived_bind_group_count))
pipeline_layout_guard.force_replace(ids.root_id, layout);
Ok(ids.root_id)
}
fn create_compute_pipeline<G: GlobalIdentityHandlerFactory>(
@ -1855,14 +1868,20 @@ impl<B: GfxBackend> Device<B> {
implicit_context: Option<ImplicitPipelineContext>,
hub: &Hub<B, G>,
token: &mut Token<Self>,
) -> Result<
(
pipeline::ComputePipeline<B>,
pipeline::ImplicitBindGroupCount,
id::PipelineLayoutId,
),
pipeline::CreateComputePipelineError,
> {
) -> Result<pipeline::ComputePipeline<B>, pipeline::CreateComputePipelineError> {
//TODO: only lock mutable if the layout is derived
let (mut pipeline_layout_guard, mut token) = hub.pipeline_layouts.write(token);
let (mut bgl_guard, mut token) = hub.bind_group_layouts.write(&mut token);
// This has to be done first, or otherwise the IDs may be pointing to entries
// that are not even in the storage.
if let Some(ref ids) = implicit_context {
pipeline_layout_guard.insert_error(ids.root_id, IMPLICIT_FAILURE);
for &bgl_id in ids.group_ids.iter() {
bgl_guard.insert_error(bgl_id, IMPLICIT_FAILURE);
}
}
if !self
.downlevel
.flags
@ -1871,10 +1890,6 @@ impl<B: GfxBackend> Device<B> {
return Err(pipeline::CreateComputePipelineError::ComputeShadersUnsupported);
}
//TODO: only lock mutable if the layout is derived
let (mut pipeline_layout_guard, mut token) = hub.pipeline_layouts.write(token);
let (mut bgl_guard, mut token) = hub.bind_group_layouts.write(&mut token);
let mut derived_group_layouts =
ArrayVec::<[binding_model::BindEntryMap; MAX_BIND_GROUPS]>::new();
@ -1882,9 +1897,9 @@ impl<B: GfxBackend> Device<B> {
let (shader_module_guard, _) = hub.shader_modules.read(&mut token);
let entry_point_name = &desc.stage.entry_point;
let shader_module = shader_module_guard.get(desc.stage.module).map_err(|_| {
pipeline::CreateComputePipelineError::Stage(validation::StageError::InvalidModule)
})?;
let shader_module = shader_module_guard
.get(desc.stage.module)
.map_err(|_| validation::StageError::InvalidModule)?;
let flag = wgt::ShaderStage::COMPUTE;
if let Some(ref interface) = shader_module.interface {
@ -1902,15 +1917,13 @@ impl<B: GfxBackend> Device<B> {
None
}
};
let _ = interface
.check_stage(
provided_layouts.as_ref().map(|p| p.as_slice()),
&mut derived_group_layouts,
&entry_point_name,
flag,
io,
)
.map_err(pipeline::CreateComputePipelineError::Stage)?;
let _ = interface.check_stage(
provided_layouts.as_ref().map(|p| p.as_slice()),
&mut derived_group_layouts,
&entry_point_name,
flag,
io,
)?;
} else if desc.layout.is_none() {
return Err(pipeline::ImplicitLayoutError::ReflectionError(flag).into());
}
@ -1926,8 +1939,8 @@ impl<B: GfxBackend> Device<B> {
// TODO
let parent = hal::pso::BasePipeline::None;
let (pipeline_layout_id, derived_bind_group_count) = match desc.layout {
Some(id) => (id, 0),
let pipeline_layout_id = match desc.layout {
Some(id) => id,
None => self.derive_pipeline_layout(
self_id,
implicit_context,
@ -1976,7 +1989,7 @@ impl<B: GfxBackend> Device<B> {
},
life_guard: LifeGuard::new(desc.label.borrow_or_default()),
};
Ok((pipeline, derived_bind_group_count, pipeline_layout_id))
Ok(pipeline)
}
fn create_render_pipeline<G: GlobalIdentityHandlerFactory>(
@ -1986,18 +1999,20 @@ impl<B: GfxBackend> Device<B> {
implicit_context: Option<ImplicitPipelineContext>,
hub: &Hub<B, G>,
token: &mut Token<Self>,
) -> Result<
(
pipeline::RenderPipeline<B>,
pipeline::ImplicitBindGroupCount,
id::PipelineLayoutId,
),
pipeline::CreateRenderPipelineError,
> {
) -> Result<pipeline::RenderPipeline<B>, pipeline::CreateRenderPipelineError> {
//TODO: only lock mutable if the layout is derived
let (mut pipeline_layout_guard, mut token) = hub.pipeline_layouts.write(token);
let (mut bgl_guard, mut token) = hub.bind_group_layouts.write(&mut token);
// This has to be done first, or otherwise the IDs may be pointing to entries
// that are not even in the storage.
if let Some(ref ids) = implicit_context {
pipeline_layout_guard.insert_error(ids.root_id, IMPLICIT_FAILURE);
for &bgl_id in ids.group_ids.iter() {
bgl_guard.insert_error(bgl_id, IMPLICIT_FAILURE);
}
}
let mut derived_group_layouts =
ArrayVec::<[binding_model::BindEntryMap; MAX_BIND_GROUPS]>::new();
@ -2080,7 +2095,7 @@ impl<B: GfxBackend> Device<B> {
});
io.insert(
attribute.shader_location,
validation::NumericType::from_vertex_format(attribute.format),
validation::InterfaceVar::vertex_attribute(attribute.format),
);
}
}
@ -2112,27 +2127,6 @@ impl<B: GfxBackend> Device<B> {
);
}
let input_assembler = conv::map_primitive_state_to_input_assembler(&desc.primitive);
let blender = hal::pso::BlendDesc {
logic_op: None, // TODO
targets: color_states
.iter()
.map(conv::map_color_target_state)
.collect(),
};
let depth_stencil = depth_stencil_state
.map(conv::map_depth_stencil_state)
.unwrap_or_default();
// TODO
let baked_states = hal::pso::BakedStates {
viewport: None,
scissor: None,
blend_color: None,
depth_bounds: None,
};
if desc.primitive.clamp_depth && !self.features.contains(wgt::Features::DEPTH_CLAMPING) {
return Err(pipeline::CreateRenderPipelineError::MissingFeature(
wgt::Features::DEPTH_CLAMPING,
@ -2162,6 +2156,29 @@ impl<B: GfxBackend> Device<B> {
);
}
let input_assembler = conv::map_primitive_state_to_input_assembler(&desc.primitive);
let mut blender = hal::pso::BlendDesc {
logic_op: None,
targets: Vec::with_capacity(color_states.len()),
};
for (i, cs) in color_states.iter().enumerate() {
let bt = conv::map_color_target_state(cs)
.map_err(|error| pipeline::CreateRenderPipelineError::ColorState(i as u8, error))?;
blender.targets.push(bt);
}
let depth_stencil = depth_stencil_state
.map(conv::map_depth_stencil_state)
.unwrap_or_default();
let baked_states = hal::pso::BakedStates {
viewport: None,
scissor: None,
blend_constants: None,
depth_bounds: None,
};
if desc.layout.is_none() {
for _ in 0..self.limits.max_bind_groups {
derived_group_layouts.push(binding_model::BindEntryMap::default());
@ -2226,19 +2243,22 @@ impl<B: GfxBackend> Device<B> {
let shader_module = shader_module_guard.get(stage.module).map_err(|_| {
pipeline::CreateRenderPipelineError::Stage {
flag,
stage: flag,
error: validation::StageError::InvalidModule,
}
})?;
if let Some(ref interface) = shader_module.interface {
let provided_layouts = match desc.layout {
Some(pipeline_layout_id) => Some(Device::get_introspection_bind_group_layouts(
pipeline_layout_guard
Some(pipeline_layout_id) => {
let pipeline_layout = pipeline_layout_guard
.get(pipeline_layout_id)
.map_err(|_| pipeline::CreateRenderPipelineError::InvalidLayout)?,
&*bgl_guard,
)),
.map_err(|_| pipeline::CreateRenderPipelineError::InvalidLayout)?;
Some(Device::get_introspection_bind_group_layouts(
pipeline_layout,
&*bgl_guard,
))
}
None => None,
};
@ -2250,7 +2270,10 @@ impl<B: GfxBackend> Device<B> {
flag,
io,
)
.map_err(|error| pipeline::CreateRenderPipelineError::Stage { flag, error })?;
.map_err(|error| pipeline::CreateRenderPipelineError::Stage {
stage: flag,
error,
})?;
validated_stages |= flag;
}
@ -2270,7 +2293,7 @@ impl<B: GfxBackend> Device<B> {
shader_module_guard
.get(fragment.stage.module)
.map_err(|_| pipeline::CreateRenderPipelineError::Stage {
flag,
stage: flag,
error: validation::StageError::InvalidModule,
})?;
@ -2295,7 +2318,7 @@ impl<B: GfxBackend> Device<B> {
io,
)
.map_err(|error| pipeline::CreateRenderPipelineError::Stage {
flag,
stage: flag,
error,
})?;
validated_stages |= flag;
@ -2314,26 +2337,26 @@ impl<B: GfxBackend> Device<B> {
if validated_stages.contains(wgt::ShaderStage::FRAGMENT) {
for (i, state) in color_states.iter().enumerate() {
match io.get(&(i as wgt::ShaderLocation)) {
Some(output) if validation::check_texture_format(state.format, output) => {}
Some(output) => {
log::warn!(
"Incompatible fragment output[{}] from shader: {:?}, expected {:?}",
i,
output,
state.format,
);
return Err(
pipeline::CreateRenderPipelineError::IncompatibleOutputFormat {
index: i as u8,
Some(ref output) => {
validation::check_texture_format(state.format, &output.ty).map_err(
|pipeline| {
pipeline::CreateRenderPipelineError::ColorState(
i as u8,
pipeline::ColorStateError::IncompatibleFormat {
pipeline,
shader: output.ty,
},
)
},
);
)?;
}
None if state.write_mask.is_empty() => {}
None => {
log::warn!("Missing fragment output[{}], expected {:?}", i, state,);
return Err(pipeline::CreateRenderPipelineError::MissingOutput {
index: i as u8,
});
return Err(pipeline::CreateRenderPipelineError::ColorState(
i as u8,
pipeline::ColorStateError::Missing,
));
}
}
}
@ -2360,8 +2383,8 @@ impl<B: GfxBackend> Device<B> {
// TODO
let parent = hal::pso::BasePipeline::None;
let (pipeline_layout_id, derived_bind_group_count) = match desc.layout {
Some(id) => (id, 0),
let pipeline_layout_id = match desc.layout {
Some(id) => id,
None => self.derive_pipeline_layout(
self_id,
implicit_context,
@ -2432,8 +2455,8 @@ impl<B: GfxBackend> Device<B> {
let mut flags = pipeline::PipelineFlags::empty();
for state in color_states.iter() {
if let Some(ref bs) = state.blend {
if bs.color.uses_color() | bs.alpha.uses_color() {
flags |= pipeline::PipelineFlags::BLEND_COLOR;
if bs.color.uses_constant() | bs.alpha.uses_constant() {
flags |= pipeline::PipelineFlags::BLEND_CONSTANT;
}
}
}
@ -2462,7 +2485,7 @@ impl<B: GfxBackend> Device<B> {
vertex_strides,
life_guard: LifeGuard::new(desc.label.borrow_or_default()),
};
Ok((pipeline, derived_bind_group_count, pipeline_layout_id))
Ok(pipeline)
}
fn wait_for_submit(
@ -3376,7 +3399,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let mut entry_map = FastHashMap::default();
for entry in desc.entries.iter() {
if entry_map.insert(entry.binding, entry.clone()).is_some() {
if entry_map.insert(entry.binding, *entry).is_some() {
break 'outer binding_model::CreateBindGroupLayoutError::ConflictBinding(
entry.binding,
);
@ -4009,7 +4032,6 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
implicit_pipeline_ids: Option<ImplicitPipelineIds<G>>,
) -> (
id::RenderPipelineId,
pipeline::ImplicitBindGroupCount,
Option<pipeline::CreateRenderPipelineError>,
) {
profiling::scope!("Device::create_render_pipeline");
@ -4035,19 +4057,23 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
});
}
let (pipeline, derived_bind_group_count, _layout_id) = match device
.create_render_pipeline(device_id, desc, implicit_context, &hub, &mut token)
{
let pipeline = match device.create_render_pipeline(
device_id,
desc,
implicit_context,
&hub,
&mut token,
) {
Ok(pair) => pair,
Err(e) => break e,
};
let id = fid.assign(pipeline, &mut token);
return (id.0, derived_bind_group_count, None);
return (id.0, None);
};
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, 0, Some(error))
(id, Some(error))
}
/// Get an ID of one of the bind group layouts. The ID adds a refcount,
@ -4137,7 +4163,6 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
implicit_pipeline_ids: Option<ImplicitPipelineIds<G>>,
) -> (
id::ComputePipelineId,
pipeline::ImplicitBindGroupCount,
Option<pipeline::CreateComputePipelineError>,
) {
profiling::scope!("Device::create_compute_pipeline");
@ -4163,19 +4188,23 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
});
}
let (pipeline, derived_bind_group_count, _layout_id) = match device
.create_compute_pipeline(device_id, desc, implicit_context, &hub, &mut token)
{
let pipeline = match device.create_compute_pipeline(
device_id,
desc,
implicit_context,
&hub,
&mut token,
) {
Ok(pair) => pair,
Err(e) => break e,
};
let id = fid.assign(pipeline, &mut token);
return (id.0, derived_bind_group_count, None);
return (id.0, None);
};
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, 0, Some(error))
(id, Some(error))
}
/// Get an ID of one of the bind group layouts. The ID adds a refcount,
@ -4525,9 +4554,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
HostMap::Write => (wgt::BufferUsage::MAP_WRITE, resource::BufferUse::MAP_WRITE),
};
if range.start % wgt::COPY_BUFFER_ALIGNMENT != 0
|| range.end % wgt::COPY_BUFFER_ALIGNMENT != 0
{
if range.start % wgt::MAP_ALIGNMENT != 0 || range.end % wgt::COPY_BUFFER_ALIGNMENT != 0 {
return Err(resource::BufferAccessError::UnalignedRange);
}
@ -4597,10 +4624,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
buffer.size - offset
};
if offset % 8 != 0 {
if offset % wgt::MAP_ALIGNMENT != 0 {
return Err(resource::BufferAccessError::UnalignedOffset { offset });
}
if range_size % 4 != 0 {
if range_size % wgt::COPY_BUFFER_ALIGNMENT != 0 {
return Err(resource::BufferAccessError::UnalignedRangeSize { range_size });
}

Просмотреть файл

@ -318,7 +318,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
trace.add(Action::WriteTexture {
to: destination.clone(),
data: data_path,
layout: data_layout.clone(),
layout: *data_layout,
size: *size,
});
}

Просмотреть файл

@ -180,6 +180,11 @@ impl<T, I: TypedId> Storage<T, I> {
self.insert_impl(index as usize, Element::Error(epoch, label.to_string()))
}
pub(crate) fn force_replace(&mut self, id: I, value: T) {
let (index, epoch, _) = id.unzip();
self.map[index as usize] = Element::Occupied(value, epoch);
}
pub(crate) fn remove(&mut self, id: I) -> Option<T> {
let (index, epoch, _) = id.unzip();
match std::mem::replace(&mut self.map[index as usize], Element::Vacant) {

Просмотреть файл

@ -111,8 +111,8 @@ pub enum CreateComputePipelineError {
InvalidLayout,
#[error("unable to derive an implicit layout")]
Implicit(#[from] ImplicitLayoutError),
#[error(transparent)]
Stage(validation::StageError),
#[error("error matching shader requirements against the pipeline")]
Stage(#[from] validation::StageError),
#[error("Internal error: {0}")]
Internal(String),
#[error(
@ -196,6 +196,19 @@ pub struct RenderPipelineDescriptor<'a> {
pub fragment: Option<FragmentState<'a>>,
}
#[derive(Clone, Debug, Error)]
pub enum ColorStateError {
#[error("output is missing")]
Missing,
#[error("output format {pipeline} is incompatible with the shader {shader}")]
IncompatibleFormat {
pipeline: validation::NumericType,
shader: validation::NumericType,
},
#[error("blend factors for {0:?} must be `One`")]
InvalidMinMaxBlendFactors(wgt::BlendComponent),
}
#[derive(Clone, Debug, Error)]
pub enum CreateRenderPipelineError {
#[error(transparent)]
@ -204,10 +217,8 @@ pub enum CreateRenderPipelineError {
InvalidLayout,
#[error("unable to derive an implicit layout")]
Implicit(#[from] ImplicitLayoutError),
#[error("missing output at index {index}")]
MissingOutput { index: u8 },
#[error("incompatible output format at index {index}")]
IncompatibleOutputFormat { index: u8 },
#[error("color state [{0}] is invalid")]
ColorState(u8, #[source] ColorStateError),
#[error("invalid sample count {0}")]
InvalidSampleCount(u32),
#[error("the number of vertex buffers {given} exceeds the limit {limit}")]
@ -235,13 +246,13 @@ pub enum CreateRenderPipelineError {
ConservativeRasterizationNonFillPolygonMode,
#[error("missing required device features {0:?}")]
MissingFeature(wgt::Features),
#[error("error in stage {flag:?}")]
#[error("error matching {stage:?} shader requirements against the pipeline")]
Stage {
flag: wgt::ShaderStage,
stage: wgt::ShaderStage,
#[source]
error: validation::StageError,
},
#[error("Internal error in stage {stage:?}: {error}")]
#[error("Internal error in {stage:?} shader: {error}")]
Internal {
stage: wgt::ShaderStage,
error: String,
@ -251,7 +262,7 @@ pub enum CreateRenderPipelineError {
bitflags::bitflags! {
#[repr(transparent)]
pub struct PipelineFlags: u32 {
const BLEND_COLOR = 1;
const BLEND_CONSTANT = 1;
const STENCIL_REFERENCE = 2;
const WRITES_DEPTH_STENCIL = 4;
}

Просмотреть файл

@ -142,7 +142,9 @@ pub enum BufferAccessError {
MissingBufferUsage(#[from] MissingBufferUsageError),
#[error("buffer is not mapped")]
NotMapped,
#[error("buffer map range does not respect `COPY_BUFFER_ALIGNMENT`")]
#[error(
"buffer map range must start aligned to `MAP_ALIGNMENT` and end to `COPY_BUFFER_ALIGNMENT`"
)]
UnalignedRange,
#[error("buffer offset invalid: offset {offset} must be multiple of 8")]
UnalignedOffset { offset: wgt::BufferAddress },
@ -444,6 +446,8 @@ pub struct Sampler<B: hal::Backend> {
pub(crate) life_guard: LifeGuard,
/// `true` if this is a comparison sampler
pub(crate) comparison: bool,
/// `true` if this is a filtering sampler
pub(crate) filtering: bool,
}
#[derive(Clone, Debug, Error)]

Просмотреть файл

@ -142,6 +142,15 @@ impl PendingTransition<BufferState> {
}
}
impl From<PendingTransition<BufferState>> for UsageConflict {
fn from(e: PendingTransition<BufferState>) -> Self {
Self::Buffer {
id: e.id.0,
combined_use: e.usage.end,
}
}
}
impl PendingTransition<TextureState> {
/// Produce the gfx-hal barrier corresponding to the transition.
pub fn into_hal<'a, B: hal::Backend>(
@ -167,6 +176,17 @@ impl PendingTransition<TextureState> {
}
}
impl From<PendingTransition<TextureState>> for UsageConflict {
fn from(e: PendingTransition<TextureState>) -> Self {
Self::Texture {
id: e.id.0,
mip_levels: e.selector.levels.start as u32..e.selector.levels.end as u32,
array_layers: e.selector.layers.start as u32..e.selector.layers.end as u32,
combined_use: e.usage.end,
}
}
}
#[derive(Clone, Debug, Error)]
pub enum UseExtendError<U: fmt::Debug> {
#[error("resource is invalid")]
@ -607,20 +627,8 @@ impl TrackerSet {
/// Merge all the trackers of another instance by extending
/// the usage. Panics on a conflict.
pub fn merge_extend(&mut self, other: &Self) -> Result<(), UsageConflict> {
self.buffers
.merge_extend(&other.buffers)
.map_err(|e| UsageConflict::Buffer {
id: e.id.0,
combined_use: e.usage.end,
})?;
self.textures
.merge_extend(&other.textures)
.map_err(|e| UsageConflict::Texture {
id: e.id.0,
mip_levels: e.selector.levels.start as u32..e.selector.levels.end as u32,
array_layers: e.selector.layers.start as u32..e.selector.layers.end as u32,
combined_use: e.usage.end,
})?;
self.buffers.merge_extend(&other.buffers)?;
self.textures.merge_extend(&other.textures)?;
self.views.merge_extend(&other.views).unwrap();
self.bind_groups.merge_extend(&other.bind_groups).unwrap();
self.samplers.merge_extend(&other.samplers).unwrap();

Просмотреть файл

@ -2,9 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use crate::{binding_model::BindEntryMap, FastHashMap};
use crate::{binding_model::BindEntryMap, FastHashMap, FastHashSet};
use naga::valid::GlobalUse;
use std::collections::hash_map::Entry;
use std::{collections::hash_map::Entry, fmt};
use thiserror::Error;
use wgt::{BindGroupLayoutEntry, BindingType};
@ -25,8 +25,8 @@ enum ResourceType {
#[derive(Debug)]
struct Resource {
group: u32,
binding: u32,
name: Option<String>,
bind: naga::ResourceBinding,
ty: ResourceType,
class: naga::StorageClass,
}
@ -38,6 +38,16 @@ enum NumericDimension {
Matrix(naga::VectorSize, naga::VectorSize),
}
impl fmt::Display for NumericDimension {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Scalar => write!(f, ""),
Self::Vector(size) => write!(f, "x{}", size as u8),
Self::Matrix(columns, rows) => write!(f, "x{}{}", columns as u8, rows as u8),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct NumericType {
dim: NumericDimension,
@ -45,9 +55,42 @@ pub struct NumericType {
width: naga::Bytes,
}
impl fmt::Display for NumericType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}{}{}", self.kind, self.width * 8, self.dim)
}
}
#[derive(Clone, Debug)]
pub struct InterfaceVar {
pub ty: NumericType,
interpolation: Option<naga::Interpolation>,
sampling: Option<naga::Sampling>,
}
impl InterfaceVar {
pub fn vertex_attribute(format: wgt::VertexFormat) -> Self {
InterfaceVar {
ty: NumericType::from_vertex_format(format),
interpolation: None,
sampling: None,
}
}
}
impl fmt::Display for InterfaceVar {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{} interpolated as {:?} with sampling {:?}",
self.ty, self.interpolation, self.sampling
)
}
}
#[derive(Debug)]
enum Varying {
Local { location: u32, ty: NumericType },
Local { location: u32, iv: InterfaceVar },
BuiltIn(naga::BuiltIn),
}
@ -63,6 +106,7 @@ struct EntryPoint {
outputs: Vec<Varying>,
resources: Vec<(naga::Handle<Resource>, GlobalUse)>,
spec_constants: Vec<SpecializationConstant>,
sampling_pairs: FastHashSet<(naga::Handle<Resource>, naga::Handle<Resource>)>,
}
#[derive(Debug)]
@ -117,8 +161,11 @@ pub enum BindingError {
Missing,
#[error("visibility flags don't include the shader stage")]
Invisible,
#[error("load/store access flags {0:?} don't match the shader")]
WrongUsage(GlobalUse),
#[error("The shader requires the load/store access flags {required:?} but only {allowed:?} is allowed")]
WrongUsage {
required: GlobalUse,
allowed: GlobalUse,
},
#[error("type on the shader side does not match the pipeline binding")]
WrongType,
#[error("buffer structure size {0}, added to one element of an unbound array, if it's the last field, ended up greater than the given `min_binding_size`")]
@ -142,12 +189,24 @@ pub enum BindingError {
BadStorageFormat(wgt::TextureFormat),
}
#[derive(Clone, Debug, Error)]
pub enum FilteringError {
#[error("integer textures can't be sampled")]
Integer,
#[error("non-filterable float texture")]
NonFilterable,
}
#[derive(Clone, Debug, Error)]
pub enum InputError {
#[error("input is not provided by the earlier stage in the pipeline")]
Missing,
#[error("input type is not compatible with the provided")]
WrongType,
#[error("input type is not compatible with the provided {0}")]
WrongType(NumericType),
#[error("input interpolation doesn't match provided {0:?}")]
InterpolationMismatch(Option<naga::Interpolation>),
#[error("input sampling doesn't match provided {0:?}")]
SamplingMismatch(Option<naga::Sampling>),
}
/// Errors produced when validating a programmable stage of a pipeline.
@ -155,19 +214,22 @@ pub enum InputError {
pub enum StageError {
#[error("shader module is invalid")]
InvalidModule,
#[error("unable to find an entry point at {0:?} stage")]
#[error("unable to find entry point '{0:?}'")]
MissingEntryPoint(String),
#[error("error matching global binding at index {binding} in group {group} against the pipeline layout: {error}")]
Binding {
group: u32,
binding: u32,
error: BindingError,
#[error("shader global {0:?} is not available in the layout pipeline layout")]
Binding(naga::ResourceBinding, #[source] BindingError),
#[error("unable to filter the texture ({texture:?}) by the sampler ({sampler:?})")]
Filtering {
texture: naga::ResourceBinding,
sampler: naga::ResourceBinding,
#[source]
error: FilteringError,
},
#[error(
"error matching the stage input at {location} against the previous stage outputs: {error}"
)]
#[error("location[{location}] {var} is not provided by the previous stage outputs")]
Input {
location: wgt::ShaderLocation,
var: InterfaceVar,
#[source]
error: InputError,
},
}
@ -253,7 +315,7 @@ impl Resource {
let global_use = match ty {
wgt::BufferBindingType::Uniform
| wgt::BufferBindingType::Storage { read_only: true } => {
GlobalUse::READ
GlobalUse::READ | GlobalUse::QUERY
}
wgt::BufferBindingType::Storage { read_only: _ } => GlobalUse::all(),
};
@ -346,7 +408,7 @@ impl Resource {
},
wgt::TextureSampleType::Depth => naga::ImageClass::Depth,
};
(class, GlobalUse::READ)
(class, GlobalUse::READ | GlobalUse::QUERY)
}
BindingType::StorageTexture {
access,
@ -356,8 +418,12 @@ impl Resource {
let naga_format = map_storage_format_to_naga(format)
.ok_or(BindingError::BadStorageFormat(format))?;
let usage = match access {
wgt::StorageTextureAccess::ReadOnly => GlobalUse::READ,
wgt::StorageTextureAccess::WriteOnly => GlobalUse::WRITE,
wgt::StorageTextureAccess::ReadOnly => {
GlobalUse::READ | GlobalUse::QUERY
}
wgt::StorageTextureAccess::WriteOnly => {
GlobalUse::WRITE | GlobalUse::QUERY
}
wgt::StorageTextureAccess::ReadWrite => GlobalUse::all(),
};
(naga::ImageClass::Storage(naga_format), usage)
@ -377,7 +443,10 @@ impl Resource {
if allowed_usage.contains(shader_usage) {
Ok(())
} else {
Err(BindingError::WrongUsage(shader_usage))
Err(BindingError::WrongUsage {
required: shader_usage,
allowed: allowed_usage,
})
}
}
@ -451,7 +520,7 @@ impl Resource {
}
impl NumericType {
pub fn from_vertex_format(format: wgt::VertexFormat) -> Self {
fn from_vertex_format(format: wgt::VertexFormat) -> Self {
use naga::{ScalarKind as Sk, VectorSize as Vs};
use wgt::VertexFormat as Vf;
@ -615,14 +684,35 @@ impl NumericType {
_ => false,
}
}
fn is_compatible_with(&self, other: &NumericType) -> bool {
if self.kind != other.kind {
return false;
}
match (self.dim, other.dim) {
(NumericDimension::Scalar, NumericDimension::Scalar) => true,
(NumericDimension::Scalar, NumericDimension::Vector(_)) => true,
(NumericDimension::Vector(_), NumericDimension::Vector(_)) => true,
(NumericDimension::Matrix(..), NumericDimension::Matrix(..)) => true,
_ => false,
}
}
}
/// Return true if the fragment `format` is covered by the provided `output`.
pub fn check_texture_format(format: wgt::TextureFormat, output: &NumericType) -> bool {
NumericType::from_texture_format(format).is_subtype_of(output)
pub fn check_texture_format(
format: wgt::TextureFormat,
output: &NumericType,
) -> Result<(), NumericType> {
let nt = NumericType::from_texture_format(format);
if nt.is_subtype_of(output) {
Ok(())
} else {
Err(nt)
}
}
pub type StageIo = FastHashMap<wgt::ShaderLocation, NumericType>;
pub type StageIo = FastHashMap<wgt::ShaderLocation, InterfaceVar>;
impl Interface {
fn populate(
@ -651,10 +741,7 @@ impl Interface {
kind: naga::ScalarKind::Float,
width,
},
naga::TypeInner::Struct {
block: _,
ref members,
} => {
naga::TypeInner::Struct { ref members, .. } => {
for member in members {
Self::populate(list, member.binding.as_ref(), member.ty, arena);
}
@ -667,9 +754,17 @@ impl Interface {
};
let varying = match binding {
Some(&naga::Binding::Location(location, _)) => Varying::Local {
Some(&naga::Binding::Location {
location,
ty: numeric_ty,
interpolation,
sampling,
}) => Varying::Local {
location,
iv: InterfaceVar {
ty: numeric_ty,
interpolation,
sampling,
},
},
Some(&naga::Binding::BuiltIn(built_in)) => Varying::BuiltIn(built_in),
None => {
@ -684,20 +779,18 @@ impl Interface {
let mut resources = naga::Arena::new();
let mut resource_mapping = FastHashMap::default();
for (var_handle, var) in module.global_variables.iter() {
let (group, binding) = match var.binding {
Some(ref br) => (br.group, br.binding),
let bind = match var.binding {
Some(ref br) => br.clone(),
_ => continue,
};
let ty = match module.types[var.ty].inner {
naga::TypeInner::Struct {
block: true,
level: naga::StructLevel::Root,
members: _,
} => {
let actual_size = info.layouter[var.ty].size;
ResourceType::Buffer {
size: wgt::BufferSize::new(actual_size as u64).unwrap(),
}
}
span,
} => ResourceType::Buffer {
size: wgt::BufferSize::new(span as u64).unwrap(),
},
naga::TypeInner::Image {
dim,
arrayed,
@ -714,8 +807,8 @@ impl Interface {
}
};
let handle = resources.append(Resource {
group,
binding,
name: var.name.clone(),
bind,
ty,
class: var.class,
});
@ -780,12 +873,13 @@ impl Interface {
.get(&pair)
.ok_or(StageError::MissingEntryPoint(pair.1))?;
// check resources visibility
for &(handle, usage) in entry_point.resources.iter() {
let res = &self.resources[handle];
let result = match given_layouts {
Some(layouts) => layouts
.get(res.group as usize)
.and_then(|map| map.get(&res.binding))
.get(res.bind.group as usize)
.and_then(|map| map.get(&res.bind.binding))
.ok_or(BindingError::Missing)
.and_then(|entry| {
if entry.visibility.contains(stage_bit) {
@ -796,11 +890,11 @@ impl Interface {
})
.and_then(|entry| res.check_binding_use(entry, usage)),
None => derived_layouts
.get_mut(res.group as usize)
.get_mut(res.bind.group as usize)
.ok_or(BindingError::Missing)
.and_then(|set| {
let ty = res.derive_binding_type(usage)?;
match set.entry(res.binding) {
match set.entry(res.bind.binding) {
Entry::Occupied(e) if e.get().ty != ty => {
return Err(BindingError::InconsistentlyDerivedType)
}
@ -809,7 +903,7 @@ impl Interface {
}
Entry::Vacant(e) => {
e.insert(BindGroupLayoutEntry {
binding: res.binding,
binding: res.bind.binding,
ty,
visibility: stage_bit,
count: None,
@ -820,30 +914,93 @@ impl Interface {
}),
};
if let Err(error) = result {
return Err(StageError::Binding {
group: res.group,
binding: res.binding,
error,
});
return Err(StageError::Binding(res.bind.clone(), error));
}
}
// check the compatibility between textures and samplers
if let Some(layouts) = given_layouts {
for &(texture_handle, sampler_handle) in entry_point.sampling_pairs.iter() {
let texture_bind = &self.resources[texture_handle].bind;
let sampler_bind = &self.resources[sampler_handle].bind;
let texture_layout = &layouts[texture_bind.group as usize][&texture_bind.binding];
let sampler_layout = &layouts[sampler_bind.group as usize][&sampler_bind.binding];
assert!(texture_layout.visibility.contains(stage_bit));
assert!(sampler_layout.visibility.contains(stage_bit));
let error = match texture_layout.ty {
wgt::BindingType::Texture {
sample_type: wgt::TextureSampleType::Float { filterable },
..
} => match sampler_layout.ty {
wgt::BindingType::Sampler {
filtering: true, ..
} if !filterable => Some(FilteringError::NonFilterable),
_ => None,
},
wgt::BindingType::Texture {
sample_type: wgt::TextureSampleType::Sint,
..
}
| wgt::BindingType::Texture {
sample_type: wgt::TextureSampleType::Uint,
..
} => Some(FilteringError::Integer),
_ => None, // unreachable, really
};
if let Some(error) = error {
return Err(StageError::Filtering {
texture: texture_bind.clone(),
sampler: sampler_bind.clone(),
error,
});
}
}
}
// check inputs compatibility
for input in entry_point.inputs.iter() {
match *input {
Varying::Local { location, ty } => {
Varying::Local { location, ref iv } => {
let result =
inputs
.get(&location)
.ok_or(InputError::Missing)
.and_then(|provided| {
if ty.is_subtype_of(provided) {
let compatible = match shader_stage {
// For vertex attributes, there are defaults filled out
// by the driver if data is not provided.
naga::ShaderStage::Vertex => {
iv.ty.is_compatible_with(&provided.ty)
}
naga::ShaderStage::Fragment => {
if iv.interpolation != provided.interpolation {
return Err(InputError::InterpolationMismatch(
provided.interpolation,
));
}
if iv.sampling != provided.sampling {
return Err(InputError::SamplingMismatch(
provided.sampling,
));
}
iv.ty.is_subtype_of(&provided.ty)
}
naga::ShaderStage::Compute => false,
};
if compatible {
Ok(())
} else {
Err(InputError::WrongType)
Err(InputError::WrongType(provided.ty))
}
});
if let Err(error) = result {
return Err(StageError::Input { location, error });
return Err(StageError::Input {
location,
var: iv.clone(),
error,
});
}
}
Varying::BuiltIn(_) => {}
@ -854,7 +1011,7 @@ impl Interface {
.outputs
.iter()
.filter_map(|output| match *output {
Varying::Local { location, ty } => Some((location, ty)),
Varying::Local { location, ref iv } => Some((location, iv.clone())),
Varying::BuiltIn(_) => None,
})
.collect();

Просмотреть файл

@ -40,6 +40,8 @@ pub const COPY_BYTES_PER_ROW_ALIGNMENT: u32 = 256;
pub const BIND_BUFFER_ALIGNMENT: BufferAddress = 256;
/// Buffer to buffer copy offsets and sizes must be aligned to this number.
pub const COPY_BUFFER_ALIGNMENT: BufferAddress = 4;
/// Size to align mappings.
pub const MAP_ALIGNMENT: BufferAddress = 8;
/// Vertex buffer strides have to be aligned to this number.
pub const VERTEX_STRIDE_ALIGNMENT: BufferAddress = 4;
/// Alignment all push constants need
@ -604,7 +606,7 @@ pub enum ShaderModel {
/// Supported physical device types.
#[repr(u8)]
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub enum DeviceType {
@ -755,18 +757,18 @@ pub enum BlendFactor {
Zero = 0,
/// 1.0
One = 1,
/// S.color
SrcColor = 2,
/// 1.0 - S.color
OneMinusSrcColor = 3,
/// S.component
Src = 2,
/// 1.0 - S.component
OneMinusSrc = 3,
/// S.alpha
SrcAlpha = 4,
/// 1.0 - S.alpha
OneMinusSrcAlpha = 5,
/// D.color
DstColor = 6,
/// 1.0 - D.color
OneMinusDstColor = 7,
/// D.component
Dst = 6,
/// 1.0 - D.component
OneMinusDst = 7,
/// D.alpha
DstAlpha = 8,
/// 1.0 - D.alpha
@ -774,9 +776,9 @@ pub enum BlendFactor {
/// min(S.alpha, 1.0 - D.alpha)
SrcAlphaSaturated = 10,
/// Constant
BlendColor = 11,
Constant = 11,
/// 1.0 - Constant
OneMinusBlendColor = 12,
OneMinusConstant = 12,
}
/// Alpha blend operation.
@ -807,7 +809,7 @@ impl Default for BlendOperation {
/// Describes the blend component of a pipeline.
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct BlendComponent {
@ -822,14 +824,14 @@ pub struct BlendComponent {
impl BlendComponent {
/// Default blending state that replaces destination with the source.
pub const REPLACE: Self = BlendComponent {
pub const REPLACE: Self = Self {
src_factor: BlendFactor::One,
dst_factor: BlendFactor::Zero,
operation: BlendOperation::Add,
};
/// Blend state of (1 * src) + ((1 - src_alpha) * dst)
pub const OVER: Self = BlendComponent {
pub const OVER: Self = Self {
src_factor: BlendFactor::One,
dst_factor: BlendFactor::OneMinusSrcAlpha,
operation: BlendOperation::Add,
@ -837,12 +839,12 @@ impl BlendComponent {
/// Returns true if the state relies on the constant color, which is
/// set independently on a render command encoder.
pub fn uses_color(&self) -> bool {
pub fn uses_constant(&self) -> bool {
match (self.src_factor, self.dst_factor) {
(BlendFactor::BlendColor, _)
| (BlendFactor::OneMinusBlendColor, _)
| (_, BlendFactor::BlendColor)
| (_, BlendFactor::OneMinusBlendColor) => true,
(BlendFactor::Constant, _)
| (BlendFactor::OneMinusConstant, _)
| (_, BlendFactor::Constant)
| (_, BlendFactor::OneMinusConstant) => true,
(_, _) => false,
}
}
@ -858,7 +860,7 @@ impl Default for BlendComponent {
///
/// See the OpenGL or Vulkan spec for more information.
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct BlendState {
@ -1007,7 +1009,7 @@ impl Default for PolygonMode {
/// Describes the state of primitive assembly and rasterization in a render pipeline.
#[repr(C)]
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct PrimitiveState {
@ -1042,7 +1044,7 @@ pub struct PrimitiveState {
/// Describes the multi-sampling state of a render pipeline.
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct MultisampleState {
@ -1718,7 +1720,7 @@ impl StencilState {
/// Describes the biasing setting for the depth target.
#[repr(C)]
#[derive(Clone, Debug, Default, PartialEq)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct DepthBiasState {
@ -1820,7 +1822,7 @@ impl Default for StencilOperation {
///
/// If you are not using stencil state, set this to [`StencilFaceState::IGNORE`].
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct StencilFaceState {
@ -1906,7 +1908,7 @@ impl Default for InputStepMode {
///
/// Arrays of these can be made with the [`vertex_attr_array`] macro. Vertex attributes are assumed to be tightly packed.
#[repr(C)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct VertexAttribute {
@ -2594,7 +2596,7 @@ impl<T> Default for RenderBundleDescriptor<Option<T>> {
/// Layout of a texture in a buffer's memory.
#[repr(C)]
#[derive(Clone, Debug, Default)]
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct ImageDataLayout {
@ -2835,7 +2837,7 @@ impl BindingType {
}
/// Describes a single binding inside a bind group.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "trace", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct BindGroupLayoutEntry {
@ -2970,7 +2972,7 @@ bitflags::bitflags! {
/// Argument buffer layout for draw_indirect commands.
#[repr(C)]
#[derive(Clone, Debug)]
#[derive(Clone, Copy, Debug)]
pub struct DrawIndirectArgs {
/// The number of vertices to draw.
pub vertex_count: u32,
@ -2984,7 +2986,7 @@ pub struct DrawIndirectArgs {
/// Argument buffer layout for draw_indexed_indirect commands.
#[repr(C)]
#[derive(Clone, Debug)]
#[derive(Clone, Copy, Debug)]
pub struct DrawIndexedIndirectArgs {
/// The number of indices to draw.
pub index_count: u32,
@ -3000,7 +3002,7 @@ pub struct DrawIndexedIndirectArgs {
/// Argument buffer layout for dispatch_indirect commands.
#[repr(C)]
#[derive(Clone, Debug)]
#[derive(Clone, Copy, Debug)]
pub struct DispatchIndirectArgs {
/// X dimension of the grid of workgroups to dispatch.
pub group_size_x: u32,

Просмотреть файл

@ -234,7 +234,7 @@ trait GlobalExt {
self_id: id::DeviceId,
action: DeviceAction,
error_buf: ErrorBuffer,
) -> Vec<u8>;
);
fn texture_action<B: wgc::hub::GfxBackend>(
&self,
self_id: id::TextureId,
@ -255,8 +255,7 @@ impl GlobalExt for Global {
self_id: id::DeviceId,
action: DeviceAction,
mut error_buf: ErrorBuffer,
) -> Vec<u8> {
let mut drop_actions = Vec::new();
) {
match action {
DeviceAction::CreateBuffer(id, desc) => {
let (_, error) = self.device_create_buffer::<B>(self_id, &desc, id);
@ -313,20 +312,11 @@ impl GlobalExt for Global {
root_id: imp.pipeline,
group_ids: &imp.bind_groups,
});
let (_, group_count, error) =
let (_, error) =
self.device_create_compute_pipeline::<B>(self_id, &desc, id, implicit_ids);
if let Some(err) = error {
error_buf.init(err);
}
if let Some(ref imp) = implicit {
for &bgl_id in imp.bind_groups[group_count as usize..].iter() {
bincode::serialize_into(
&mut drop_actions,
&DropAction::BindGroupLayout(bgl_id),
)
.unwrap();
}
}
}
DeviceAction::CreateRenderPipeline(id, desc, implicit) => {
let implicit_ids = implicit
@ -335,20 +325,11 @@ impl GlobalExt for Global {
root_id: imp.pipeline,
group_ids: &imp.bind_groups,
});
let (_, group_count, error) =
let (_, error) =
self.device_create_render_pipeline::<B>(self_id, &desc, id, implicit_ids);
if let Some(err) = error {
error_buf.init(err);
}
if let Some(ref imp) = implicit {
for &bgl_id in imp.bind_groups[group_count as usize..].iter() {
bincode::serialize_into(
&mut drop_actions,
&DropAction::BindGroupLayout(bgl_id),
)
.unwrap();
}
}
}
DeviceAction::CreateRenderBundle(_id, desc, _base) => {
wgc::command::RenderBundleEncoder::new(&desc, self_id, None).unwrap();
@ -360,7 +341,6 @@ impl GlobalExt for Global {
}
}
}
drop_actions
}
fn texture_action<B: wgc::hub::GfxBackend>(
@ -478,12 +458,10 @@ pub unsafe extern "C" fn wgpu_server_device_action(
global: &Global,
self_id: id::DeviceId,
byte_buf: &ByteBuf,
drop_byte_buf: &mut ByteBuf,
error_buf: ErrorBuffer,
) {
let action = bincode::deserialize(byte_buf.as_slice()).unwrap();
let drop_actions = gfx_select!(self_id => global.device_action(self_id, action, error_buf));
*drop_byte_buf = ByteBuf::from_vec(drop_actions);
gfx_select!(self_id => global.device_action(self_id, action, error_buf));
}
#[no_mangle]

0
third_party/rust/ahash/smhasher/clone_smhasher.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/ext/debug_marker.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/ext/debug_report.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/ext/debug_utils.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/khr/android_surface.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/khr/display.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/khr/display_swapchain.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/khr/surface.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/khr/swapchain.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/khr/wayland_surface.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/khr/win32_surface.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/khr/xcb_surface.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/khr/xlib_surface.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/mvk/ios_surface.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/mvk/macos_surface.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/nv/mesh_shader.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/ash/src/extensions/nv/ray_tracing.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/authenticator/testing/run_cross.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/bindgen/src/codegen/bitfield_unit.rs поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/bit-set/deploy-docs.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/bit-vec/crusader.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/bit-vec/deploy-docs.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/bytemuck/scripts/travis.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cose/tools/certs/certs.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-coreaudio/.githooks/pre-push поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-coreaudio/install_git_hook.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-coreaudio/install_rustfmt_clippy.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-coreaudio/run_device_tests.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-coreaudio/run_sanitizers.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-coreaudio/run_tests.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/cmake/sanitizers-cmake/cmake/asan-wrapper поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/scripts/fuse_gtest_files.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/scripts/gen_gtest_pred_impl.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/scripts/gtest-config.in поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/scripts/pump.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/scripts/upload.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/scripts/upload_gtest.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_break_on_failure_unittest.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_catch_exceptions_test.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_color_test.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_env_var_test.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_filter_unittest.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_help_test.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_list_tests_unittest.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_output_test.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_shuffle_test.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_test_utils.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_throw_on_failure_test.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_uninitialized_test.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_xml_outfiles_test.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_xml_output_unittest.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/googletest/test/gtest_xml_test_utils.py поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/cubeb-sys/libcubeb/scan-build-install.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/failure/build-docs.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/freetype/configure поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/freetype/etc/bindgen.sh поставляемый Normal file → Executable file
Просмотреть файл

0
third_party/rust/fuchsia-zircon/tools/gen_status.py поставляемый Normal file → Executable file
Просмотреть файл

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"90303c618ad2c02733e2f4f995d3af4fc34616c2bf4a3afb7829c7a8f1ecf1fd","src/lib.rs":"575e61823dc942028e5b71bf30900180bcdb51ec28832b51d4bb78b41818a4c5"},"package":null}
{"files":{"Cargo.toml":"90303c618ad2c02733e2f4f995d3af4fc34616c2bf4a3afb7829c7a8f1ecf1fd","src/lib.rs":"f64e02aec86b3c391e85c41ea4f4cb9eb0c5868f67e5461261e15e866df5ee4d"},"package":null}

2
third_party/rust/gfx-auxil/src/lib.rs поставляемый
Просмотреть файл

@ -65,7 +65,7 @@ pub fn read_spirv<R: io::Read + io::Seek>(mut x: R) -> io::Result<Vec<u32>> {
"input length not divisible by 4",
));
}
if size > usize::max_value() as u64 {
if size > usize::MAX as u64 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "input too long"));
}
let words = (size / 4) as usize;

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"d42fde1925a161b942a1c563246e29b6866aed9a86a613fd3b12b2324e1a4c97","README.md":"13b17f879e00fec29de8d7ba7c24163e9eddc9c5ce173464c48762653b3041ce","shaders/blit.hlsl":"92a8b404ee956ceff2728ec8dd68969fba4c32a79f4d879f069a294f245a867c","shaders/clear.hlsl":"b715a0d8ccebd858531de845fdb3f1b31f25d3f62266238cd1d417006a07957c","shaders/copy.hlsl":"c71b2df8691068d450d3216b54a5a0315f1e17bcd75aec3b4f46b5e3521945c3","src/conv.rs":"436fa263d869024018e54e4f6fd5c0bcaec2424deed871bc97f9854779dac53e","src/debug.rs":"60a2a7cac9cbced6385f560d7b171c4a8eb9a644d8ac219671e1e0fcc8a2439f","src/device.rs":"ac413afabc9191352260b33486b32aaff201a0fa384cc13fd48d48221224aa09","src/dxgi.rs":"7265f4a24b48013c67aac33d456c2aae210b9d597170721738833015fba974bf","src/internal.rs":"0f5ebadf821a532c3820bd86d344bd9db09e466a70aa8cc50c4776058674a5ff","src/lib.rs":"e2d4123643222c637be5c63ab4a0f7ad908e364acf1aa8a068cc66034fbbfd83","src/shader.rs":"0c3c2475578cd322ab6c737732dec00d0893924f3d397f3d326e53f3bc90e9e5"},"package":null}
{"files":{"Cargo.toml":"d42fde1925a161b942a1c563246e29b6866aed9a86a613fd3b12b2324e1a4c97","README.md":"13b17f879e00fec29de8d7ba7c24163e9eddc9c5ce173464c48762653b3041ce","shaders/blit.hlsl":"92a8b404ee956ceff2728ec8dd68969fba4c32a79f4d879f069a294f245a867c","shaders/clear.hlsl":"b715a0d8ccebd858531de845fdb3f1b31f25d3f62266238cd1d417006a07957c","shaders/copy.hlsl":"c71b2df8691068d450d3216b54a5a0315f1e17bcd75aec3b4f46b5e3521945c3","src/conv.rs":"436fa263d869024018e54e4f6fd5c0bcaec2424deed871bc97f9854779dac53e","src/debug.rs":"60a2a7cac9cbced6385f560d7b171c4a8eb9a644d8ac219671e1e0fcc8a2439f","src/device.rs":"453186b234d8b85e8d3b7c3e298ed5046d6935c5affd5091e90143040145c4bd","src/dxgi.rs":"7265f4a24b48013c67aac33d456c2aae210b9d597170721738833015fba974bf","src/internal.rs":"0f5ebadf821a532c3820bd86d344bd9db09e466a70aa8cc50c4776058674a5ff","src/lib.rs":"97b94c1b0011162a411448954d3768f182e5ecd49f54d82c7067f7c68bf5b48a","src/shader.rs":"0c3c2475578cd322ab6c737732dec00d0893924f3d397f3d326e53f3bc90e9e5"},"package":null}

Просмотреть файл

@ -768,13 +768,17 @@ impl Device {
}
}
}
image::ViewKind::D1 | image::ViewKind::D1Array | image::ViewKind::D3 | image::ViewKind::Cube | image::ViewKind::CubeArray => {
image::ViewKind::D1
| image::ViewKind::D1Array
| image::ViewKind::D3
| image::ViewKind::Cube
| image::ViewKind::CubeArray => {
warn!(
"3D and cube views are not supported for the image, kind: {:?}",
info.kind
);
return Err(image::ViewCreationError::BadKind(info.view_kind));
},
}
}
let mut dsv = ptr::null_mut();
@ -1790,6 +1794,7 @@ impl device::Device<Backend> for Device {
view_kind: image::ViewKind,
format: format::Format,
_swizzle: format::Swizzle,
usage: image::Usage,
range: image::SubresourceRange,
) -> Result<ImageView, image::ViewCreationError> {
let is_array = image.kind.num_layers() > 1;
@ -1827,7 +1832,7 @@ impl device::Device<Backend> for Device {
range.level_start as _,
),
format,
srv_handle: if image.usage.intersects(image::Usage::SAMPLED) {
srv_handle: if usage.intersects(image::Usage::SAMPLED) {
let srv = self.view_image_as_shader_resource(&srv_info)?;
if let Some(ref mut name) = debug_name {
@ -1838,7 +1843,7 @@ impl device::Device<Backend> for Device {
} else {
None
},
rtv_handle: if image.usage.contains(image::Usage::COLOR_ATTACHMENT) {
rtv_handle: if usage.contains(image::Usage::COLOR_ATTACHMENT) {
let rtv = self.view_image_as_render_target(&info)?;
if let Some(ref mut name) = debug_name {
@ -1849,7 +1854,7 @@ impl device::Device<Backend> for Device {
} else {
None
},
uav_handle: if image.usage.contains(image::Usage::STORAGE) {
uav_handle: if usage.contains(image::Usage::STORAGE) {
let uav = self.view_image_as_unordered_access(&info)?;
if let Some(ref mut name) = debug_name {
@ -1860,7 +1865,7 @@ impl device::Device<Backend> for Device {
} else {
None
},
dsv_handle: if image.usage.contains(image::Usage::DEPTH_STENCIL_ATTACHMENT) {
dsv_handle: if usage.contains(image::Usage::DEPTH_STENCIL_ATTACHMENT) {
if let Some(dsv) = self.view_image_as_depth_stencil(&info, None).ok() {
if let Some(ref mut name) = debug_name {
set_debug_name_with_suffix(&dsv, name, " -- DSV");
@ -1873,11 +1878,13 @@ impl device::Device<Backend> for Device {
} else {
None
},
rodsv_handle: if image.usage.contains(image::Usage::DEPTH_STENCIL_ATTACHMENT)
rodsv_handle: if usage.contains(image::Usage::DEPTH_STENCIL_ATTACHMENT)
&& self.internal.downlevel.read_only_depth_stencil
{
if let Some(rodsv) =
self.view_image_as_depth_stencil(&info, Some(image.format.is_stencil())).ok() {
if let Some(rodsv) = self
.view_image_as_depth_stencil(&info, Some(image.format.is_stencil()))
.ok()
{
if let Some(ref mut name) = debug_name {
set_debug_name_with_suffix(&rodsv, name, " -- DSV");
}

Просмотреть файл

@ -622,7 +622,7 @@ impl hal::Instance<Backend> for Instance {
limits,
dynamic_pipeline_states: hal::DynamicStates::VIEWPORT
| hal::DynamicStates::SCISSOR
| hal::DynamicStates::BLEND_COLOR
| hal::DynamicStates::BLEND_CONSTANTS
| hal::DynamicStates::DEPTH_BOUNDS
| hal::DynamicStates::STENCIL_REFERENCE,
downlevel,
@ -1686,7 +1686,7 @@ impl CommandBufferState {
let blend_color = if let Some(ref pipeline) = self.graphics_pipeline {
pipeline
.baked_states
.blend_color
.blend_constants
.or(self.blend_factor)
.unwrap_or([0f32; 4])
} else {

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"35330be366ddac11c8650d97bd2a0e7960d25ed3d516055d68ab1d77641abd86","README.md":"de987fd4e01bc95d01094ba75140d92b0c34041768616b69e615c0a3b7dd4968","shaders/blit.hlsl":"0c95317cd14b0ae71459d74c3e5658acac0baf8476525d2063c143e300180fe6","src/command.rs":"afa24d666dc4c2d4d838b07c684215be6b56ec633e30cc5d475f9e4b54f61bf1","src/conv.rs":"89b47062783a91ccb5be00453d1a0ece9d0fee521cfd784570922899d22f6ebc","src/descriptors_cpu.rs":"3aea4aa606ddf2240aa96ca8df7d9c531cb41e04f3e9e67690e124d1571b33b8","src/device.rs":"a24a3c261c61d1b24067d30369780be52ed818f5680e620db0097c7c5a921749","src/internal.rs":"6f45623b7c6ca293310d295c87810fe4f2b7343189a88ad92b8d882ffedbe76b","src/lib.rs":"a070e65126dc95c283cbee03063b550934622738ef937dc838a5c05250bc6602","src/pool.rs":"8f611e9b1c61ade025d7c787df375c6c927b196ebcffc34b429c978132b71022","src/resource.rs":"7fbe010306b4388c40ccf0538dc6d611cbe6d39d88435cd0e6a0db8c41206454","src/root_constants.rs":"1f74217772e9702a5493e6e6b43c17eaf0462e3f4cee4fa9a5f93318397953f4","src/window.rs":"07042a60a0d0a972bf1c9a3b28868cf1abaa673188dbdfb6f202a50577c60ae0"},"package":null}
{"files":{"Cargo.toml":"35330be366ddac11c8650d97bd2a0e7960d25ed3d516055d68ab1d77641abd86","README.md":"de987fd4e01bc95d01094ba75140d92b0c34041768616b69e615c0a3b7dd4968","shaders/blit.hlsl":"0c95317cd14b0ae71459d74c3e5658acac0baf8476525d2063c143e300180fe6","src/command.rs":"d22111d9e6ba43e1e9701701645792307d8f31ef89e5d43ada3f08ec209f625b","src/conv.rs":"89b47062783a91ccb5be00453d1a0ece9d0fee521cfd784570922899d22f6ebc","src/descriptors_cpu.rs":"3aea4aa606ddf2240aa96ca8df7d9c531cb41e04f3e9e67690e124d1571b33b8","src/device.rs":"9417c5d388194d8cdb6d373ed335f3d7c9fd403e2fc72ca6a3ff01b3b077856f","src/internal.rs":"6f45623b7c6ca293310d295c87810fe4f2b7343189a88ad92b8d882ffedbe76b","src/lib.rs":"6ecd14730d9d61aeadf133becf182eb15d501725c0f0c36003034a6500f09d7c","src/pool.rs":"8f611e9b1c61ade025d7c787df375c6c927b196ebcffc34b429c978132b71022","src/resource.rs":"461c3ffbc6c0f8f8b78ffc1f8b66358b26b09538bb5cdf215283d25a47af32a2","src/root_constants.rs":"1f74217772e9702a5493e6e6b43c17eaf0462e3f4cee4fa9a5f93318397953f4","src/window.rs":"52e3567332c7cd48d4cf0e0c9877d843ff6dede068334289612871a45c5255b2"},"package":null}

Просмотреть файл

@ -2080,7 +2080,7 @@ impl com::CommandBuffer<Backend> for CommandBuffer {
if let Some(ref rect) = pipeline.baked_states.scissor {
self.set_scissors(0, iter::once(rect.clone()));
}
if let Some(color) = pipeline.baked_states.blend_color {
if let Some(color) = pipeline.baked_states.blend_constants {
self.set_blend_constants(color);
}
if let Some(ref bounds) = pipeline.baked_states.depth_bounds {

Просмотреть файл

@ -1113,6 +1113,7 @@ impl Device {
if !winerror::SUCCEEDED(hr) {
error!("error on swapchain creation 0x{:x}", hr);
return Err(w::SwapchainError::Unknown);
}
let (swap_chain3, hr3) = swap_chain1.cast::<dxgi1_4::IDXGISwapChain3>();
@ -1217,7 +1218,6 @@ impl Device {
surface_type: image_unbound.format.base_format().0,
kind: image_unbound.kind,
mip_levels: image_unbound.mip_levels,
usage: image_unbound.usage,
default_view_format: image_unbound.view_format,
view_caps: image_unbound.view_caps,
descriptor: image_unbound.desc,
@ -2191,7 +2191,7 @@ impl d::Device<B> for Device {
},
SampleMask: match desc.multisampling {
Some(ref ms) => ms.sample_mask as u32,
None => UINT::max_value(),
None => UINT::MAX,
},
RasterizerState: conv::map_rasterizer(&desc.rasterizer, desc.multisampling.is_some()),
DepthStencilState: conv::map_depth_stencil(&desc.depth_stencil),
@ -2781,6 +2781,7 @@ impl d::Device<B> for Device {
view_kind: image::ViewKind,
format: format::Format,
swizzle: format::Swizzle,
usage: image::Usage,
range: image::SubresourceRange,
) -> Result<r::ImageView, image::ViewCreationError> {
let image = image.expect_bound();
@ -2815,12 +2816,12 @@ impl d::Device<B> for Device {
//Note: we allow RTV/DSV/SRV/UAV views to fail to be created here,
// because we don't know if the user will even need to use them.
//Update: now we have `usage`, but some of the users (like `wgpu`)
// still don't know ahead of time what it needs to be.
Ok(r::ImageView {
resource: image.resource,
handle_srv: if image
.usage
.intersects(image::Usage::SAMPLED | image::Usage::INPUT_ATTACHMENT)
handle_srv: if usage.intersects(image::Usage::SAMPLED | image::Usage::INPUT_ATTACHMENT)
{
let info = if range.aspects.contains(format::Aspects::DEPTH) {
conv::map_format_shader_depth(surface_format).map(|format| ViewInfo {
@ -2847,7 +2848,7 @@ impl d::Device<B> for Device {
} else {
None
},
handle_rtv: if image.usage.contains(image::Usage::COLOR_ATTACHMENT) {
handle_rtv: if usage.contains(image::Usage::COLOR_ATTACHMENT) {
// This view is not necessarily going to be rendered to, even
// if the image supports that in general.
match self.view_image_as_render_target(&info) {
@ -2857,12 +2858,12 @@ impl d::Device<B> for Device {
} else {
r::RenderTargetHandle::None
},
handle_uav: if image.usage.contains(image::Usage::STORAGE) {
handle_uav: if usage.contains(image::Usage::STORAGE) {
self.view_image_as_storage(&info).ok()
} else {
None
},
handle_dsv: if image.usage.contains(image::Usage::DEPTH_STENCIL_ATTACHMENT) {
handle_dsv: if usage.contains(image::Usage::DEPTH_STENCIL_ATTACHMENT) {
match conv::map_format_dsv(surface_format) {
Some(dsv_format) => self
.view_image_as_depth_stencil(&ViewInfo {
@ -3374,8 +3375,8 @@ impl d::Device<B> for Device {
// This block handles overflow when converting to u32 and always rounds up
// The Vulkan specification allows to wait more than specified
let timeout_ms = {
if timeout_ns > (<u32>::max_value() as u64) * 1_000_000 {
<u32>::max_value()
if timeout_ns > (<u32>::MAX as u64) * 1_000_000 {
<u32>::MAX
} else {
((timeout_ns + 999_999) / 1_000_000) as u32
}

Просмотреть файл

@ -1448,7 +1448,7 @@ impl hal::Instance<Backend> for Instance {
},
dynamic_pipeline_states: hal::DynamicStates::VIEWPORT
| hal::DynamicStates::SCISSOR
| hal::DynamicStates::BLEND_COLOR
| hal::DynamicStates::BLEND_CONSTANTS
| hal::DynamicStates::STENCIL_REFERENCE,
downlevel: hal::DownlevelProperties::all_enabled(),
..PhysicalDeviceProperties::default()

Просмотреть файл

@ -251,7 +251,6 @@ pub struct ImageBound {
pub(crate) surface_type: format::SurfaceType,
pub(crate) kind: image::Kind,
pub(crate) mip_levels: image::Level,
pub(crate) usage: image::Usage,
pub(crate) default_view_format: Option<DXGI_FORMAT>,
pub(crate) view_caps: image::ViewCapabilities,
pub(crate) descriptor: d3d12::D3D12_RESOURCE_DESC,

Просмотреть файл

@ -277,7 +277,6 @@ impl w::PresentationSurface<Backend> for Surface {
surface_type: base_format.0,
kind,
mip_levels: 1,
usage: sc.usage,
default_view_format: None,
view_caps: i::ViewCapabilities::empty(),
descriptor,

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"ea56292266b10d8449fbf4d9d5c5a9cc8cd1902731d145f284ac2210b89e9518","src/buffer.rs":"1a275e7a1d4bebe594256709e7ee166222518178bd6112cd45c29d4aa6d002dd","src/descriptor.rs":"0689f381dcb0a8603167495373d6cfae9d50f2b5017ab3e364bc838949548827","src/image.rs":"83dba8bae97e06ced4f8030f208566dd773b773be14bc56f10da92dedec041f0","src/lib.rs":"85310f1e3ee61f13ef292c8765dbeb7fe75e99b567699b53d714c1e6daa12ec4","src/memory.rs":"abba2a8943dccf79cc67de3ce33dc534606fe3838220504a1330f773c7bf0ac6"},"package":null}
{"files":{"Cargo.toml":"ea56292266b10d8449fbf4d9d5c5a9cc8cd1902731d145f284ac2210b89e9518","src/buffer.rs":"1a275e7a1d4bebe594256709e7ee166222518178bd6112cd45c29d4aa6d002dd","src/descriptor.rs":"0689f381dcb0a8603167495373d6cfae9d50f2b5017ab3e364bc838949548827","src/image.rs":"83dba8bae97e06ced4f8030f208566dd773b773be14bc56f10da92dedec041f0","src/lib.rs":"fa80d2e782f95798488931648c6e26c83470dbf3f8f942c0b3362d723dd3e0e0","src/memory.rs":"abba2a8943dccf79cc67de3ce33dc534606fe3838220504a1330f773c7bf0ac6"},"package":null}

Просмотреть файл

@ -368,6 +368,7 @@ impl device::Device<Backend> for Device {
_: hal::image::ViewKind,
_: format::Format,
_: format::Swizzle,
_: hal::image::Usage,
_: hal::image::SubresourceRange,
) -> Result<(), hal::image::ViewCreationError> {
Ok(())

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"00019d96a907b42d29a25efa1ee01b4d9b43b3e3746c776842367fd4da414d9b","README.md":"e08409da89ea3f102953c99fb62661f4e434cdb925e69b8964faf0a93861c338","shaders/blit.metal":"b243873ac0d7ded37b199d17d1a7b53d5332b4a57bfa22f99dcf60273730be45","shaders/clear.metal":"796a612c1cb48e46fc94b7227feaab993d7ddeed293b69e9f09b2dd88e6a1189","shaders/fill.metal":"2642b5df62f8eb2246a442137d083010d2a3132110d9be4eb25b479123098d25","shaders/gfx-shaders-ios-simulator.metallib":"561a9b5d91e03e904bae3ffff20f5325cc2ba0653315ae9b8b790ce91597152c","shaders/gfx-shaders-ios.metallib":"e1aad872cf5a5dc1e7dd22cb37124d22a4dac9f9f682b8cce3a490c8ea90589f","shaders/gfx-shaders-macos.metallib":"c07140adb3699dad71b3d7117c3caba7c1823089067391c8b6c9d308ce077785","shaders/macros.h":"a4550ac7c180935c2edb57aa7a5f8442b53f1f3dc65df8cc800d0afb8289cdeb","src/command.rs":"a6aad67798dcea7cc989744768567ed974a734c2c3eeaff1ff6df2a25e12a5dd","src/conversions.rs":"29c3eada40ab90759124e7967a6b587aec45bdac67e6c5129f21453b2510128e","src/device.rs":"938c4e2206ef0a5b181c8524e34fff713fb8ddde868114a568e3022948fe47ef","src/internal.rs":"042a64ac4f47d915d6c8e3c981641bb7bacefe83080f0058353d36ce92f60f42","src/lib.rs":"d743b7460b187b5c906b248f188f6c211f8a5ff12cf14d2e9509cc754e77ea0f","src/native.rs":"441700ed4f669bdcd32fd0061227b0956ffe52bca1a23f42187d6f02f2a231b0","src/soft.rs":"dd22363485a638922c977539ce3a1642d551576c58df456ab9c1f26d4d7e1dd3","src/window.rs":"9aab7b6bd579f0b8db9e5767151f5a17388fb4e51119b2b74927823724f54ee8"},"package":null}
{"files":{"Cargo.toml":"9d1f5920647f988741edd575468c4cd32c8415d9ee56b8052d34644bf7741694","README.md":"e08409da89ea3f102953c99fb62661f4e434cdb925e69b8964faf0a93861c338","shaders/blit.metal":"b243873ac0d7ded37b199d17d1a7b53d5332b4a57bfa22f99dcf60273730be45","shaders/clear.metal":"796a612c1cb48e46fc94b7227feaab993d7ddeed293b69e9f09b2dd88e6a1189","shaders/fill.metal":"2642b5df62f8eb2246a442137d083010d2a3132110d9be4eb25b479123098d25","shaders/gfx-shaders-ios-simulator.metallib":"561a9b5d91e03e904bae3ffff20f5325cc2ba0653315ae9b8b790ce91597152c","shaders/gfx-shaders-ios.metallib":"e1aad872cf5a5dc1e7dd22cb37124d22a4dac9f9f682b8cce3a490c8ea90589f","shaders/gfx-shaders-macos.metallib":"c07140adb3699dad71b3d7117c3caba7c1823089067391c8b6c9d308ce077785","shaders/macros.h":"a4550ac7c180935c2edb57aa7a5f8442b53f1f3dc65df8cc800d0afb8289cdeb","src/command.rs":"bac7ac76f1e802dfcbc58c569e6b33860e8722a85fc4772a2a029628b5b1ea0d","src/conversions.rs":"2aa8a7237b5fcc035fff4cdc7e9e46e18fdb2c099eedcba3a2a8bcd63d4c6c74","src/device.rs":"a0cd493bea8bc123977ca3eff47480777b198290022535bdb44422b9d2edf191","src/internal.rs":"042a64ac4f47d915d6c8e3c981641bb7bacefe83080f0058353d36ce92f60f42","src/lib.rs":"8c60edad2e18f8066babafac93583d6deaa1e17a3a990eb447ac9e1bfe9ec9f4","src/native.rs":"cdf69e7ee978fac6f440b75d2bbce637901611efdbd93904e34136dc4d16508c","src/pipeline_cache.rs":"7acaa09d28307d893f978710c6970f9826bfa51c374a5c2c9d9765f6b1ef4970","src/soft.rs":"efc89c1755cef9cebc74665105286d5f12b8486bdc95c6a6613398b9eee673b8","src/window.rs":"85a7c55e0a80f95e1104eebb54f34cb3f1f4ce86b4d00d16462e3e583105572f"},"package":null}

Просмотреть файл

@ -16,6 +16,7 @@ edition = "2018"
default = []
signpost = []
cross = ["spirv_cross", "auxil", "naga/spv-out"]
pipeline-cache = ["tempfile", "serde", "bincode", "naga/serialize", "naga/deserialize", "naga/spv-out"]
[lib]
name = "gfx_backend_metal"
@ -29,7 +30,7 @@ copyless = "0.1.4"
fxhash = "0.2.1"
log = { version = "0.4" }
dispatch = { version = "0.2", optional = true }
metal = { git = "https://github.com/gfx-rs/metal-rs", rev="439c986eb7a9b91e88b61def2daa66e4043fcbef", features = ["private"] }
metal = { git = "https://github.com/gfx-rs/metal-rs", rev="78f632d194c7c16d18b71d7373c4080847d110b0", features = ["private"] }
foreign-types = "0.3"
objc = "0.2.5"
block = "0.1"
@ -37,6 +38,10 @@ cocoa-foundation = "0.1"
parking_lot = "0.11"
storage-map = "0.3"
raw-window-handle = "0.3"
profiling = { version = "0.1.10", default-features = false }
tempfile = { version = "3.2", optional = true }
serde = { version = "1", features = ["serde_derive"], optional = true }
bincode = { version = "1", optional = true }
[dependencies.auxil]
package = "gfx-auxil"
@ -52,7 +57,7 @@ optional = true
[dependencies.naga]
git = "https://github.com/gfx-rs/naga"
tag = "gfx-20"
tag = "gfx-22"
features = ["spv-in", "msl-out"]
# This forces docs.rs to build the crate on mac, otherwise the build fails

Просмотреть файл

@ -203,14 +203,17 @@ impl RenderPassDescriptorCache {
let desc = rp_desc.color_attachments().object_at(i as _).unwrap();
desc.set_texture(None);
desc.set_resolve_texture(None);
desc.set_level(0);
desc.set_slice(0);
}
if let Some(desc) = rp_desc.depth_attachment() {
desc.set_texture(None);
desc.set_level(0);
desc.set_slice(0);
}
if let Some(desc) = rp_desc.stencil_attachment() {
desc.set_texture(None);
desc.set_level(0);
desc.set_slice(0);
}
self.spare_descriptors.push(rp_desc);
@ -1924,6 +1927,15 @@ where
offset,
);
}
Cmd::InsertDebugMarker { ref name } => {
encoder.insert_debug_signpost(name.as_ref());
}
Cmd::PushDebugMarker { ref name } => {
encoder.push_debug_group(name.as_ref());
}
Cmd::PopDebugGroup => {
encoder.pop_debug_group();
}
}
}
@ -2209,6 +2221,7 @@ impl hal::queue::Queue<Backend> for Queue {
Iw: Iterator<Item = (&'a native::Semaphore, pso::PipelineStage)>,
Is: Iterator<Item = &'a native::Semaphore>,
{
profiling::scope!("submit");
debug!("submitting with fence {:?}", fence);
self.wait(wait_semaphores.map(|(s, _)| s));
@ -2229,6 +2242,7 @@ impl hal::queue::Queue<Backend> for Queue {
let mut release_sinks = Vec::new();
for cmd_buffer in command_buffers {
profiling::scope!("submit command buffer");
let mut inner = cmd_buffer.inner.borrow_mut();
let CommandBufferInner {
ref sink,
@ -2411,6 +2425,7 @@ impl hal::queue::Queue<Backend> for Queue {
image: window::SwapchainImage,
wait_semaphore: Option<&mut native::Semaphore>,
) -> Result<Option<Suboptimal>, PresentError> {
profiling::scope!("present");
if let Some(semaphore) = wait_semaphore {
if let Some(ref system) = semaphore.system {
system.wait(!0);
@ -3672,6 +3687,7 @@ impl com::CommandBuffer<Backend> for CommandBuffer {
}
unsafe fn bind_graphics_pipeline(&mut self, pipeline: &native::GraphicsPipeline) {
profiling::scope!("bind_graphics_pipeline");
let mut inner = self.inner.borrow_mut();
let mut pre = inner.sink().pre_render();
@ -3775,7 +3791,7 @@ impl com::CommandBuffer<Backend> for CommandBuffer {
pre.issue(com);
}
}
if let Some(ref color) = pipeline.baked_states.blend_color {
if let Some(ref color) = pipeline.baked_states.blend_constants {
pre.issue(self.state.set_blend_color(color));
}
}
@ -3790,6 +3806,8 @@ impl com::CommandBuffer<Backend> for CommandBuffer {
I: Iterator<Item = &'a native::DescriptorSet>,
J: Iterator<Item = com::DescriptorSetOffset>,
{
profiling::scope!("bind_graphics_descriptor_sets");
let vbuf_count = self
.state
.render_pso
@ -3823,6 +3841,8 @@ impl com::CommandBuffer<Backend> for CommandBuffer {
layouts: _,
ref resources,
} => {
profiling::scope!("bind descriptor set");
let end_offsets = self.state.bind_set(
pso::ShaderStageFlags::VERTEX | pso::ShaderStageFlags::FRAGMENT,
&*pool.read(),
@ -3943,6 +3963,7 @@ impl com::CommandBuffer<Backend> for CommandBuffer {
}
unsafe fn bind_compute_pipeline(&mut self, pipeline: &native::ComputePipeline) {
profiling::scope!("bind_compute_pipeline");
self.state.compute_pso = Some(pipeline.raw.clone());
self.state.work_group_size = pipeline.work_group_size;
@ -3970,6 +3991,7 @@ impl com::CommandBuffer<Backend> for CommandBuffer {
I: Iterator<Item = &'a native::DescriptorSet>,
J: Iterator<Item = com::DescriptorSetOffset>,
{
profiling::scope!("bind_compute_descriptor_sets");
self.state.resources_cs.pre_allocate(&pipe_layout.total.cs);
let mut dynamic_offset_iter = dynamic_offsets;
@ -3987,6 +4009,8 @@ impl com::CommandBuffer<Backend> for CommandBuffer {
layouts: _,
ref resources,
} => {
profiling::scope!("bind descriptor set");
let end_offsets = self.state.bind_set(
pso::ShaderStageFlags::COMPUTE,
&*pool.read(),
@ -4871,13 +4895,27 @@ impl com::CommandBuffer<Backend> for CommandBuffer {
}
}
unsafe fn insert_debug_marker(&mut self, _name: &str, _color: u32) {
//TODO
unsafe fn insert_debug_marker(&mut self, name: &str, _color: u32) {
self.inner
.borrow_mut()
.sink()
.pre_render()
.issue(soft::RenderCommand::InsertDebugMarker { name })
}
unsafe fn begin_debug_marker(&mut self, _name: &str, _color: u32) {
//TODO
unsafe fn begin_debug_marker(&mut self, name: &str, _color: u32) {
self.inner
.borrow_mut()
.sink()
.pre_render()
.issue(soft::RenderCommand::PushDebugMarker { name })
}
unsafe fn end_debug_marker(&mut self) {
//TODO
self.inner
.borrow_mut()
.sink()
.pre_render()
.issue(soft::RenderCommand::PopDebugGroup)
}
}

Просмотреть файл

@ -9,6 +9,7 @@ use hal::{
IndexType,
};
use metal::*;
use std::num::NonZeroU32;
impl PrivateCapabilities {
pub fn map_format(&self, format: Format) -> Option<MTLPixelFormat> {
@ -803,3 +804,141 @@ pub fn map_naga_stage_to_cross(stage: naga::ShaderStage) -> spirv_cross::spirv::
naga::ShaderStage::Compute => Em::GlCompute,
}
}
#[cfg(feature = "cross")]
pub fn map_sampler_data_to_cross(info: &image::SamplerDesc) -> spirv_cross::msl::SamplerData {
use spirv_cross::msl;
fn map_address(wrap: image::WrapMode) -> msl::SamplerAddress {
match wrap {
image::WrapMode::Tile => msl::SamplerAddress::Repeat,
image::WrapMode::Mirror => msl::SamplerAddress::MirroredRepeat,
image::WrapMode::Clamp => msl::SamplerAddress::ClampToEdge,
image::WrapMode::Border => msl::SamplerAddress::ClampToBorder,
image::WrapMode::MirrorClamp => {
unimplemented!("https://github.com/grovesNL/spirv_cross/issues/138")
}
}
}
let lods = info.lod_range.start.0..info.lod_range.end.0;
msl::SamplerData {
coord: if info.normalized {
msl::SamplerCoord::Normalized
} else {
msl::SamplerCoord::Pixel
},
min_filter: match info.min_filter {
image::Filter::Nearest => msl::SamplerFilter::Nearest,
image::Filter::Linear => msl::SamplerFilter::Linear,
},
mag_filter: match info.mag_filter {
image::Filter::Nearest => msl::SamplerFilter::Nearest,
image::Filter::Linear => msl::SamplerFilter::Linear,
},
mip_filter: match info.min_filter {
image::Filter::Nearest if info.lod_range.end.0 < 0.5 => msl::SamplerMipFilter::None,
image::Filter::Nearest => msl::SamplerMipFilter::Nearest,
image::Filter::Linear => msl::SamplerMipFilter::Linear,
},
s_address: map_address(info.wrap_mode.0),
t_address: map_address(info.wrap_mode.1),
r_address: map_address(info.wrap_mode.2),
compare_func: match info.comparison {
Some(func) => unsafe { std::mem::transmute(map_compare_function(func) as u32) },
None => msl::SamplerCompareFunc::Always,
},
border_color: match info.border {
image::BorderColor::TransparentBlack => msl::SamplerBorderColor::TransparentBlack,
image::BorderColor::OpaqueBlack => msl::SamplerBorderColor::OpaqueBlack,
image::BorderColor::OpaqueWhite => msl::SamplerBorderColor::OpaqueWhite,
},
lod_clamp_min: lods.start.into(),
lod_clamp_max: lods.end.into(),
max_anisotropy: info.anisotropy_clamp.map_or(0, |aniso| aniso as i32),
planes: 0,
resolution: msl::FormatResolution::_444,
chroma_filter: msl::SamplerFilter::Nearest,
x_chroma_offset: msl::ChromaLocation::CositedEven,
y_chroma_offset: msl::ChromaLocation::CositedEven,
swizzle: [
msl::ComponentSwizzle::Identity,
msl::ComponentSwizzle::Identity,
msl::ComponentSwizzle::Identity,
msl::ComponentSwizzle::Identity,
],
ycbcr_conversion_enable: false,
ycbcr_model: msl::SamplerYCbCrModelConversion::RgbIdentity,
ycbcr_range: msl::SamplerYCbCrRange::ItuFull,
bpc: 8,
}
}
pub fn map_sampler_data_to_naga(
info: &image::SamplerDesc,
) -> naga::back::msl::sampler::InlineSampler {
use naga::back::msl::sampler as sm;
fn map_address(wrap: image::WrapMode) -> sm::Address {
match wrap {
image::WrapMode::Tile => sm::Address::Repeat,
image::WrapMode::Mirror => sm::Address::MirroredRepeat,
image::WrapMode::Clamp => sm::Address::ClampToEdge,
image::WrapMode::Border => sm::Address::ClampToBorder,
image::WrapMode::MirrorClamp => {
error!("Unsupported address mode - MirrorClamp");
sm::Address::ClampToEdge
}
}
}
sm::InlineSampler {
coord: if info.normalized {
sm::Coord::Normalized
} else {
sm::Coord::Pixel
},
min_filter: match info.min_filter {
image::Filter::Nearest => sm::Filter::Nearest,
image::Filter::Linear => sm::Filter::Linear,
},
mag_filter: match info.mag_filter {
image::Filter::Nearest => sm::Filter::Nearest,
image::Filter::Linear => sm::Filter::Linear,
},
mip_filter: match info.min_filter {
image::Filter::Nearest if info.lod_range.end.0 < 0.5 => None,
image::Filter::Nearest => Some(sm::Filter::Nearest),
image::Filter::Linear => Some(sm::Filter::Linear),
},
address: [
map_address(info.wrap_mode.0),
map_address(info.wrap_mode.1),
map_address(info.wrap_mode.2),
],
compare_func: match info.comparison {
Some(func) => match func {
Comparison::Never => sm::CompareFunc::Never,
Comparison::Less => sm::CompareFunc::Less,
Comparison::LessEqual => sm::CompareFunc::LessEqual,
Comparison::Equal => sm::CompareFunc::Equal,
Comparison::GreaterEqual => sm::CompareFunc::GreaterEqual,
Comparison::Greater => sm::CompareFunc::Greater,
Comparison::NotEqual => sm::CompareFunc::NotEqual,
Comparison::Always => sm::CompareFunc::Always,
},
None => sm::CompareFunc::Never,
},
border_color: match info.border {
image::BorderColor::TransparentBlack => sm::BorderColor::TransparentBlack,
image::BorderColor::OpaqueBlack => sm::BorderColor::OpaqueBlack,
image::BorderColor::OpaqueWhite => sm::BorderColor::OpaqueWhite,
},
lod_clamp: if info.lod_range.start.0 > 0.0 || info.lod_range.end.0 < 100.0 {
Some(info.lod_range.start.0..info.lod_range.end.0)
} else {
None
},
max_anisotropy: info
.anisotropy_clamp
.and_then(|aniso| NonZeroU32::new(aniso as u32)),
}
}

Просмотреть файл

@ -1,5 +1,5 @@
#[cfg(feature = "cross")]
use crate::internal::FastStorageMap;
#[cfg(feature = "pipeline-cache")]
use crate::pipeline_cache;
use crate::{
command, conversions as conv, internal::Channel, native as n, AsNative, Backend, FastHashMap,
OnlineRecording, QueueFamily, ResourceIndex, Shared, VisibilityShared,
@ -31,8 +31,9 @@ use objc::{
};
use parking_lot::Mutex;
#[cfg(feature = "cross")]
use std::collections::{hash_map::Entry, BTreeMap};
use std::collections::BTreeMap;
#[cfg(feature = "pipeline-cache")]
use std::io::Write;
use std::{
cmp, iter, mem,
ops::Range,
@ -61,6 +62,7 @@ fn get_final_function(
function_specialization: bool,
) -> Result<metal::Function, FunctionError> {
type MTLFunctionConstant = Object;
profiling::scope!("get_final_function");
let mut mtl_function = library.get_function(entry, None).map_err(|e| {
error!(
@ -140,7 +142,7 @@ pub struct Device {
features: hal::Features,
pub online_recording: OnlineRecording,
pub always_prefer_naga: bool,
#[cfg(feature = "cross")]
#[cfg(any(feature = "pipeline-cache", feature = "cross"))]
spv_options: naga::back::spv::Options,
}
unsafe impl Send for Device {}
@ -259,7 +261,7 @@ impl adapter::PhysicalDevice<Backend> for PhysicalDevice {
queue_group.add_queue(command::Queue::new(self.shared.clone()));
}
#[cfg(feature = "cross")]
#[cfg(any(feature = "pipeline-cache", feature = "cross"))]
let spv_options = {
use naga::back::spv;
let capabilities = [
@ -297,7 +299,7 @@ impl adapter::PhysicalDevice<Backend> for PhysicalDevice {
features: requested_features,
online_recording: OnlineRecording::default(),
always_prefer_naga: false,
#[cfg(feature = "cross")]
#[cfg(any(feature = "pipeline-cache", feature = "cross"))]
spv_options,
};
@ -588,17 +590,19 @@ impl Device {
stage: naga::ShaderStage,
) -> Result<n::ModuleInfo, String> {
use spirv_cross::ErrorCode as Ec;
let module = spirv_cross::spirv::Module::from_words(raw_data);
profiling::scope!("compile_shader_library_cross");
// now parse again using the new overrides
let mut ast =
let mut ast = {
profiling::scope!("spvc::parse");
let module = spirv_cross::spirv::Module::from_words(raw_data);
spirv_cross::spirv::Ast::<spirv_cross::msl::Target>::parse(&module).map_err(|err| {
match err {
Ec::CompilationError(msg) => msg,
Ec::Unhandled => "Unexpected parse error".into(),
}
})?;
})?
};
auxil::spirv_cross_specialize_ast(&mut ast, specialization)?;
@ -613,10 +617,13 @@ impl Device {
Ec::Unhandled => "Unexpected entry point error".into(),
})?;
let shader_code = ast.compile().map_err(|err| match err {
Ec::CompilationError(msg) => msg,
Ec::Unhandled => "Unknown compile error".into(),
})?;
let shader_code = {
profiling::scope!("spvc::compile");
ast.compile().map_err(|err| match err {
Ec::CompilationError(msg) => msg,
Ec::Unhandled => "Unknown compile error".into(),
})?
};
let mut entry_point_map = n::EntryPointMap::default();
for entry_point in entry_points {
@ -650,10 +657,13 @@ impl Device {
let options = metal::CompileOptions::new();
options.set_language_version(msl_version);
let library = device
.lock()
.new_library_with_source(shader_code.as_ref(), &options)
.map_err(|err| err.to_string())?;
let library = {
profiling::scope!("Metal::new_library_with_source");
device
.lock()
.new_library_with_source(shader_code.as_ref(), &options)
.map_err(|err| err.to_string())?
};
Ok(n::ModuleInfo {
library,
@ -666,9 +676,21 @@ impl Device {
device: &Mutex<metal::Device>,
shader: &d::NagaShader,
naga_options: &naga::back::msl::Options,
pipeline_options: &naga::back::msl::PipelineOptions,
#[cfg(feature = "pipeline-cache")] spv_hash: u64,
#[cfg(feature = "pipeline-cache")] spv_to_msl_cache: Option<&pipeline_cache::SpvToMsl>,
) -> Result<n::ModuleInfo, String> {
let (source, info) =
match naga::back::msl::write_string(&shader.module, &shader.info, naga_options) {
profiling::scope!("compile_shader_library_naga");
let get_module_info = || {
profiling::scope!("naga::write_string");
let (source, info) = match naga::back::msl::write_string(
&shader.module,
&shader.info,
naga_options,
pipeline_options,
) {
Ok(pair) => pair,
Err(e) => {
warn!("Naga: {:?}", e);
@ -676,23 +698,48 @@ impl Device {
}
};
let mut entry_point_map = n::EntryPointMap::default();
for (ep, internal_name) in shader
.module
.entry_points
.iter()
.zip(info.entry_point_names)
{
entry_point_map.insert(
(ep.stage, ep.name.clone()),
n::EntryPoint {
internal_name,
work_group_size: ep.workgroup_size,
},
);
}
let mut entry_point_map = n::EntryPointMap::default();
for (ep, internal_name) in shader
.module
.entry_points
.iter()
.zip(info.entry_point_names)
{
entry_point_map.insert(
(ep.stage, ep.name.clone()),
n::EntryPoint {
internal_name,
work_group_size: ep.workgroup_size,
},
);
}
debug!("Naga generated shader:\n{}", source);
debug!("Naga generated shader:\n{}", source);
Ok(n::SerializableModuleInfo {
source,
entry_point_map,
rasterization_enabled: true, //TODO
})
};
#[cfg(feature = "pipeline-cache")]
let module_info = if let Some(spv_to_msl_cache) = spv_to_msl_cache {
let key = pipeline_cache::SpvToMslKey {
options: naga_options.clone(),
pipeline_options: pipeline_options.clone(),
spv_hash,
};
spv_to_msl_cache
.get_or_create_with(&key, || get_module_info().unwrap())
.clone()
} else {
get_module_info()?
};
#[cfg(not(feature = "pipeline-cache"))]
let module_info = get_module_info()?;
let options = metal::CompileOptions::new();
let msl_version = match naga_options.lang_version {
@ -707,22 +754,26 @@ impl Device {
};
options.set_language_version(msl_version);
let library = device
.lock()
.new_library_with_source(source.as_ref(), &options)
.map_err(|err| {
warn!("Naga generated shader:\n{}", source);
warn!("Failed to compile: {}", err);
format!("{:?}", err)
})?;
let library = {
profiling::scope!("Metal::new_library_with_source");
device
.lock()
.new_library_with_source(module_info.source.as_ref(), &options)
.map_err(|err| {
warn!("Naga generated shader:\n{}", module_info.source);
warn!("Failed to compile: {}", err);
format!("{:?}", err)
})?
};
Ok(n::ModuleInfo {
library,
entry_point_map,
rasterization_enabled: true, //TODO
entry_point_map: module_info.entry_point_map,
rasterization_enabled: module_info.rasterization_enabled,
})
}
#[cfg_attr(not(feature = "pipeline-cache"), allow(unused_variables))]
fn load_shader(
&self,
ep: &pso::EntryPoint<Backend>,
@ -731,10 +782,14 @@ impl Device {
pipeline_cache: Option<&n::PipelineCache>,
stage: naga::ShaderStage,
) -> Result<(metal::Library, metal::Function, metal::MTLSize, bool), pso::CreationError> {
let _profiling_tag = match stage {
naga::ShaderStage::Vertex => "vertex",
naga::ShaderStage::Fragment => "fragment",
naga::ShaderStage::Compute => "compute",
};
profiling::scope!("load_shader", [_profiling_tag]);
let device = &self.shared.device;
#[cfg(feature = "cross")]
let (module_map, info_guard);
let info_owned;
#[cfg(feature = "cross")]
let mut compiler_options = layout.spirv_cross_options.clone();
@ -745,72 +800,60 @@ impl Device {
compiler_options.enable_point_size_builtin =
primitive_class == MTLPrimitiveTopologyClass::Point;
}
let options_clone;
let naga_options = match primitive_class {
MTLPrimitiveTopologyClass::Point => {
options_clone = naga::back::msl::Options {
allow_point_size: true,
..layout.naga_options.clone()
};
&options_clone
}
_ => &layout.naga_options,
let pipeline_options = naga::back::msl::PipelineOptions {
allow_point_size: match primitive_class {
MTLPrimitiveTopologyClass::Point => true,
_ => false,
},
};
let info = match pipeline_cache {
let info = {
let mut result = Err(String::new());
if ep.module.prefer_naga {
result = match ep.module.naga {
Ok(ref shader) => Self::compile_shader_library_naga(
device,
shader,
&layout.naga_options,
&pipeline_options,
#[cfg(feature = "pipeline-cache")]
ep.module.spv_hash,
#[cfg(feature = "pipeline-cache")]
pipeline_cache.as_ref().map(|cache| &cache.spv_to_msl),
),
Err(ref e) => Err(e.clone()),
}
}
#[cfg(feature = "cross")]
Some(cache) => {
module_map = cache
.modules
.get_or_create_with(&compiler_options, FastStorageMap::default);
info_guard = module_map.get_or_create_with(&ep.module.spv, || {
Self::compile_shader_library_cross(
device,
&ep.module.spv,
&compiler_options,
self.shared.private_caps.msl_version,
&ep.specialization,
stage,
)
.unwrap()
});
&*info_guard
if result.is_err() {
result = Self::compile_shader_library_cross(
device,
&ep.module.spv,
&compiler_options,
self.shared.private_caps.msl_version,
&ep.specialization,
stage,
);
}
_ => {
let mut result = Err(String::new());
if ep.module.prefer_naga {
result = match ep.module.naga {
Ok(ref shader) => {
Self::compile_shader_library_naga(device, shader, naga_options)
}
Err(ref e) => Err(e.clone()),
}
}
#[cfg(feature = "cross")]
if result.is_err() {
result = Self::compile_shader_library_cross(
if result.is_err() && !ep.module.prefer_naga {
result = match ep.module.naga {
Ok(ref shader) => Self::compile_shader_library_naga(
device,
&ep.module.spv,
&compiler_options,
self.shared.private_caps.msl_version,
&ep.specialization,
stage,
);
shader,
&layout.naga_options,
&pipeline_options,
#[cfg(feature = "pipeline-cache")]
ep.module.spv_hash,
#[cfg(feature = "pipeline-cache")]
pipeline_cache.as_ref().map(|cache| &cache.spv_to_msl),
),
Err(ref e) => Err(e.clone()),
}
if result.is_err() && !ep.module.prefer_naga {
result = match ep.module.naga {
Ok(ref shader) => {
Self::compile_shader_library_naga(device, shader, naga_options)
}
Err(ref e) => Err(e.clone()),
}
}
info_owned = result.map_err(|e| {
let error = format!("Error compiling the shader {:?}", e);
pso::CreationError::ShaderCreationError(stage.into(), error)
})?;
&info_owned
}
result.map_err(|e| {
let error = format!("Error compiling the shader {:?}", e);
pso::CreationError::ShaderCreationError(stage.into(), error)
})?
};
let lib = info.library.clone();
@ -923,74 +966,6 @@ impl Device {
Some(descriptor)
}
#[cfg(feature = "cross")]
fn make_sampler_data(info: &image::SamplerDesc) -> spirv_cross::msl::SamplerData {
use spirv_cross::msl;
fn map_address(wrap: image::WrapMode) -> msl::SamplerAddress {
match wrap {
image::WrapMode::Tile => msl::SamplerAddress::Repeat,
image::WrapMode::Mirror => msl::SamplerAddress::MirroredRepeat,
image::WrapMode::Clamp => msl::SamplerAddress::ClampToEdge,
image::WrapMode::Border => msl::SamplerAddress::ClampToBorder,
image::WrapMode::MirrorClamp => {
unimplemented!("https://github.com/grovesNL/spirv_cross/issues/138")
}
}
}
let lods = info.lod_range.start.0..info.lod_range.end.0;
msl::SamplerData {
coord: if info.normalized {
msl::SamplerCoord::Normalized
} else {
msl::SamplerCoord::Pixel
},
min_filter: match info.min_filter {
image::Filter::Nearest => msl::SamplerFilter::Nearest,
image::Filter::Linear => msl::SamplerFilter::Linear,
},
mag_filter: match info.mag_filter {
image::Filter::Nearest => msl::SamplerFilter::Nearest,
image::Filter::Linear => msl::SamplerFilter::Linear,
},
mip_filter: match info.min_filter {
image::Filter::Nearest if info.lod_range.end.0 < 0.5 => msl::SamplerMipFilter::None,
image::Filter::Nearest => msl::SamplerMipFilter::Nearest,
image::Filter::Linear => msl::SamplerMipFilter::Linear,
},
s_address: map_address(info.wrap_mode.0),
t_address: map_address(info.wrap_mode.1),
r_address: map_address(info.wrap_mode.2),
compare_func: match info.comparison {
Some(func) => unsafe { mem::transmute(conv::map_compare_function(func) as u32) },
None => msl::SamplerCompareFunc::Always,
},
border_color: match info.border {
image::BorderColor::TransparentBlack => msl::SamplerBorderColor::TransparentBlack,
image::BorderColor::OpaqueBlack => msl::SamplerBorderColor::OpaqueBlack,
image::BorderColor::OpaqueWhite => msl::SamplerBorderColor::OpaqueWhite,
},
lod_clamp_min: lods.start.into(),
lod_clamp_max: lods.end.into(),
max_anisotropy: info.anisotropy_clamp.map_or(0, |aniso| aniso as i32),
planes: 0,
resolution: msl::FormatResolution::_444,
chroma_filter: msl::SamplerFilter::Nearest,
x_chroma_offset: msl::ChromaLocation::CositedEven,
y_chroma_offset: msl::ChromaLocation::CositedEven,
swizzle: [
msl::ComponentSwizzle::Identity,
msl::ComponentSwizzle::Identity,
msl::ComponentSwizzle::Identity,
msl::ComponentSwizzle::Identity,
],
ycbcr_conversion_enable: false,
ycbcr_model: msl::SamplerYCbCrModelConversion::RgbIdentity,
ycbcr_range: msl::SamplerYCbCrRange::ItuFull,
bpc: 8,
}
}
}
impl hal::device::Device<Backend> for Device {
@ -1152,10 +1127,11 @@ impl hal::device::Device<Backend> for Device {
push_constant_buffer: None,
},
];
let mut binding_map = FastHashMap::default();
let mut binding_map = BTreeMap::default();
let mut argument_buffer_bindings = FastHashMap::default();
let mut inline_samplers = Vec::new();
#[cfg(feature = "cross")]
let mut const_samplers = BTreeMap::new();
let mut cross_const_samplers = BTreeMap::new();
let mut infos = Vec::new();
// First, place the push constants
@ -1199,14 +1175,13 @@ impl hal::device::Device<Backend> for Device {
match *set_layout {
n::DescriptorSetLayout::Emulated {
layouts: ref desc_layouts,
#[cfg(feature = "cross")]
ref immutable_samplers,
..
} => {
#[cfg(feature = "cross")]
for (&binding, immutable_sampler) in immutable_samplers.iter() {
//TODO: array support?
const_samplers.insert(
cross_const_samplers.insert(
spirv_cross::msl::SamplerLocation {
desc_set: set_index as u32,
binding,
@ -1252,8 +1227,19 @@ impl hal::device::Device<Backend> for Device {
} else {
None
},
sampler: if layout.content.contains(n::DescriptorContent::SAMPLER) {
Some(info.counters.samplers as _)
sampler: if layout
.content
.contains(n::DescriptorContent::IMMUTABLE_SAMPLER)
{
let immutable_sampler = &immutable_samplers[&layout.binding];
let handle = inline_samplers.len()
as naga::back::msl::InlineSamplerIndex;
inline_samplers.push(immutable_sampler.data.clone());
Some(naga::back::msl::BindSamplerTarget::Inline(handle))
} else if layout.content.contains(n::DescriptorContent::SAMPLER) {
Some(naga::back::msl::BindSamplerTarget::Resource(
info.counters.samplers as _,
))
} else {
None
},
@ -1330,7 +1316,10 @@ impl hal::device::Device<Backend> for Device {
msl::ResourceBinding {
buffer_id: target.buffer.map_or(!0, |id| id as u32),
texture_id: target.texture.map_or(!0, |id| id as u32),
sampler_id: target.sampler.map_or(!0, |id| id as u32),
sampler_id: match target.sampler {
Some(naga::back::msl::BindSamplerTarget::Resource(id)) => id as u32,
_ => !0,
},
count: 0,
},
);
@ -1373,7 +1362,7 @@ impl hal::device::Device<Backend> for Device {
);
}
// other properties
compiler_options.const_samplers = const_samplers;
compiler_options.const_samplers = cross_const_samplers;
compiler_options.enable_argument_buffers = self.shared.private_caps.argument_buffers;
compiler_options.force_zero_initialized_variables = true;
compiler_options.force_native_arrays = true;
@ -1394,9 +1383,20 @@ impl hal::device::Device<Backend> for Device {
MTLLanguageVersion::V2_3 => (2, 3),
},
binding_map,
inline_samplers,
spirv_cross_compatibility: cfg!(feature = "cross"),
fake_missing_bindings: false,
allow_point_size: false,
push_constants_map: naga::back::msl::PushConstantsMap {
vs_buffer: stage_infos[0]
.push_constant_buffer
.map(|buffer_index| buffer_index as naga::back::msl::Slot),
fs_buffer: stage_infos[1]
.push_constant_buffer
.map(|buffer_index| buffer_index as naga::back::msl::Slot),
cs_buffer: stage_infos[2]
.push_constant_buffer
.map(|buffer_index| buffer_index as naga::back::msl::Slot),
},
};
Ok(n::PipelineLayout {
@ -1433,71 +1433,133 @@ impl hal::device::Device<Backend> for Device {
})
}
#[cfg(not(feature = "pipeline-cache"))]
unsafe fn create_pipeline_cache(
&self,
_data: Option<&[u8]>,
) -> Result<n::PipelineCache, d::OutOfMemory> {
Ok(n::PipelineCache {
#[cfg(feature = "cross")]
modules: FastStorageMap::default(),
})
Ok(())
}
#[cfg(feature = "pipeline-cache")]
unsafe fn create_pipeline_cache(
&self,
data: Option<&[u8]>,
) -> Result<n::PipelineCache, d::OutOfMemory> {
let device = self.shared.device.lock();
let create_binary_archive = |data: &[u8]| {
if self.shared.private_caps.supports_binary_archives {
let descriptor = metal::BinaryArchiveDescriptor::new();
// We need to keep the temp file alive so that it doesn't get deleted until after a
// binary archive has been created.
let _temp_file = if !data.is_empty() {
// It would be nice to use a `data:text/plain;base64` url here and just pass in a
// base64-encoded version of the data, but metal validation doesn't like that:
// -[MTLDebugDevice newBinaryArchiveWithDescriptor:error:]:1046: failed assertion `url, if not nil, must be a file URL.'
let temp_file = tempfile::NamedTempFile::new().unwrap();
temp_file.as_file().write_all(&data).unwrap();
let url = metal::URL::new_with_string(&format!(
"file://{}",
temp_file.path().display()
));
descriptor.set_url(&url);
Some(temp_file)
} else {
None
};
Ok(Some(pipeline_cache::BinaryArchive {
inner: device
.new_binary_archive_with_descriptor(&descriptor)
.map_err(|_| d::OutOfMemory::Device)?,
is_empty: AtomicBool::new(data.is_empty()),
}))
} else {
Ok(None)
}
};
if let Some(data) = data.filter(|data| !data.is_empty()) {
let pipeline_cache: pipeline_cache::SerializablePipelineCache =
bincode::deserialize(data).unwrap();
Ok(n::PipelineCache {
binary_archive: create_binary_archive(&pipeline_cache.binary_archive)?,
spv_to_msl: pipeline_cache::load_spv_to_msl_cache(pipeline_cache.spv_to_msl),
})
} else {
Ok(n::PipelineCache {
binary_archive: create_binary_archive(&[])?,
spv_to_msl: Default::default(),
})
}
}
#[cfg(not(feature = "pipeline-cache"))]
unsafe fn get_pipeline_cache_data(
&self,
_cache: &n::PipelineCache,
) -> Result<Vec<u8>, d::OutOfMemory> {
//empty
Ok(Vec::new())
}
#[cfg(feature = "pipeline-cache")]
unsafe fn get_pipeline_cache_data(
&self,
cache: &n::PipelineCache,
) -> Result<Vec<u8>, d::OutOfMemory> {
let binary_archive = || {
let binary_archive = match cache.binary_archive {
Some(ref binary_archive) => binary_archive,
None => return Ok(Vec::new()),
};
// Without this, we get an extremely vague "Serialization of binaries to file failed"
// error when serializing an empty binary archive.
if binary_archive.is_empty.load(Ordering::Relaxed) {
return Ok(Vec::new());
}
let temp_path = tempfile::NamedTempFile::new().unwrap().into_temp_path();
let tmp_file_url =
metal::URL::new_with_string(&format!("file://{}", temp_path.display()));
binary_archive
.inner
.serialize_to_url(&tmp_file_url)
.unwrap();
let bytes = std::fs::read(&temp_path).unwrap();
Ok(bytes)
};
Ok(
bincode::serialize(&pipeline_cache::SerializablePipelineCache {
binary_archive: &binary_archive()?,
spv_to_msl: pipeline_cache::serialize_spv_to_msl_cache(&cache.spv_to_msl),
})
.unwrap(),
)
}
unsafe fn destroy_pipeline_cache(&self, _cache: n::PipelineCache) {
//drop
}
#[cfg_attr(not(feature = "cross"), allow(unused_variables))]
unsafe fn merge_pipeline_caches<'a, I>(
&self,
target: &mut n::PipelineCache,
sources: I,
_target: &mut n::PipelineCache,
_sources: I,
) -> Result<(), d::OutOfMemory>
where
I: Iterator<Item = &'a n::PipelineCache>,
{
#[cfg(feature = "cross")]
{
//TODO: reduce the locking here
let mut dst = target.modules.whole_write();
for source in sources {
let src = source.modules.whole_write();
for (key, value) in src.iter() {
let storage = dst
.entry(key.clone())
.or_insert_with(FastStorageMap::default);
let mut dst_module = storage.whole_write();
let src_module = value.whole_write();
for (key_module, value_module) in src_module.iter() {
match dst_module.entry(key_module.clone()) {
Entry::Vacant(em) => {
em.insert(value_module.clone());
}
Entry::Occupied(em) => {
if em.get().library.as_ptr() != value_module.library.as_ptr()
|| em.get().entry_point_map != value_module.entry_point_map
{
warn!(
"Merged module don't match, target: {:?}, source: {:?}",
em.get(),
value_module
);
}
}
}
}
}
}
}
warn!("`merge_pipeline_caches` is not currently implemented on the Metal backend.");
Ok(())
}
@ -1506,7 +1568,9 @@ impl hal::device::Device<Backend> for Device {
pipeline_desc: &pso::GraphicsPipelineDesc<'a, Backend>,
cache: Option<&n::PipelineCache>,
) -> Result<n::GraphicsPipeline, pso::CreationError> {
debug!("create_graphics_pipeline {:#?}", pipeline_desc);
profiling::scope!("create_graphics_pipeline");
trace!("create_graphics_pipeline {:#?}", pipeline_desc);
let pipeline = metal::RenderPipelineDescriptor::new();
let pipeline_layout = &pipeline_desc.layout;
let (rp_attachments, subpass) = {
@ -1798,7 +1862,16 @@ impl hal::device::Device<Backend> for Device {
pipeline.set_label(name);
}
device
profiling::scope!("Metal::new_render_pipeline_state");
#[cfg(feature = "pipeline-cache")]
if let Some(binary_archive) = pipeline_cache::pipeline_cache_to_binary_archive(cache) {
pipeline.set_binary_archives(&[&binary_archive.inner]);
}
let pipeline_state = device
// Replace this with `new_render_pipeline_state_with_fail_on_binary_archive_miss`
// to debug that the cache is actually working.
.new_render_pipeline_state(&pipeline)
.map(|raw| n::GraphicsPipeline {
vs_lib,
@ -1818,7 +1891,21 @@ impl hal::device::Device<Backend> for Device {
.map_err(|err| {
error!("PSO creation failed: {}", err);
pso::CreationError::Other
})
})?;
// We need to add the pipline descriptor to the binary archive after creating the
// pipeline, otherwise `new_render_pipeline_state_with_fail_on_binary_archive_miss`
// succeeds when it shouldn't.
#[cfg(feature = "pipeline-cache")]
if let Some(binary_archive) = pipeline_cache::pipeline_cache_to_binary_archive(cache) {
binary_archive
.inner
.add_render_pipeline_functions_with_descriptor(&pipeline)
.unwrap();
binary_archive.is_empty.store(false, Ordering::Relaxed);
}
Ok(pipeline_state)
}
unsafe fn create_compute_pipeline<'a>(
@ -1826,7 +1913,8 @@ impl hal::device::Device<Backend> for Device {
pipeline_desc: &pso::ComputePipelineDesc<'a, Backend>,
cache: Option<&n::PipelineCache>,
) -> Result<n::ComputePipeline, pso::CreationError> {
debug!("create_compute_pipeline {:?}", pipeline_desc);
profiling::scope!("create_compute_pipeline");
trace!("create_compute_pipeline {:?}", pipeline_desc);
let pipeline = metal::ComputePipelineDescriptor::new();
let (cs_lib, cs_function, work_group_size, _) = self.load_shader(
@ -1841,7 +1929,15 @@ impl hal::device::Device<Backend> for Device {
pipeline.set_label(name);
}
self.shared
profiling::scope!("Metal::new_compute_pipeline_state");
#[cfg(feature = "pipeline-cache")]
if let Some(binary_archive) = pipeline_cache::pipeline_cache_to_binary_archive(cache) {
pipeline.set_binary_archives(&[&binary_archive.inner]);
}
let pipeline_state = self
.shared
.device
.lock()
.new_compute_pipeline_state(&pipeline)
@ -1854,7 +1950,20 @@ impl hal::device::Device<Backend> for Device {
.map_err(|err| {
error!("PSO creation failed: {}", err);
pso::CreationError::Other
})
})?;
// We need to add the pipline descriptor to the binary archive after creating the
// pipeline, see `create_graphics_pipeline`.
#[cfg(feature = "pipeline-cache")]
if let Some(binary_archive) = pipeline_cache::pipeline_cache_to_binary_archive(cache) {
binary_archive
.inner
.add_compute_pipeline_functions_with_descriptor(&pipeline)
.unwrap();
binary_archive.is_empty.store(false, Ordering::Relaxed)
}
Ok(pipeline_state)
}
unsafe fn create_framebuffer<I>(
@ -1870,10 +1979,13 @@ impl hal::device::Device<Backend> for Device {
&self,
raw_data: &[u32],
) -> Result<n::ShaderModule, d::ShaderError> {
profiling::scope!("create_shader_module");
Ok(n::ShaderModule {
prefer_naga: self.always_prefer_naga,
#[cfg(feature = "cross")]
spv: raw_data.to_vec(),
#[cfg(feature = "pipeline-cache")]
spv_hash: fxhash::hash64(raw_data),
naga: {
let options = naga::front::spv::Options {
adjust_coordinate_space: !self.features.contains(hal::Features::NDC_Y_UP),
@ -1900,15 +2012,21 @@ impl hal::device::Device<Backend> for Device {
&self,
shader: d::NagaShader,
) -> Result<n::ShaderModule, (d::ShaderError, d::NagaShader)> {
profiling::scope!("create_shader_module_from_naga");
#[cfg(any(feature = "pipeline-cache", feature = "cross"))]
let spv = match naga::back::spv::write_vec(&shader.module, &shader.info, &self.spv_options)
{
Ok(spv) => spv,
Err(e) => return Err((d::ShaderError::CompilationFailed(format!("{}", e)), shader)),
};
Ok(n::ShaderModule {
prefer_naga: true,
#[cfg(feature = "pipeline-cache")]
spv_hash: fxhash::hash64(&spv),
#[cfg(feature = "cross")]
spv: match naga::back::spv::write_vec(&shader.module, &shader.info, &self.spv_options) {
Ok(spv) => spv,
Err(e) => {
return Err((d::ShaderError::CompilationFailed(format!("{}", e)), shader))
}
},
spv,
naga: Ok(shader),
})
}
@ -1918,12 +2036,13 @@ impl hal::device::Device<Backend> for Device {
info: &image::SamplerDesc,
) -> Result<n::Sampler, d::AllocationError> {
Ok(n::Sampler {
raw: match self.make_sampler_descriptor(&info) {
raw: match self.make_sampler_descriptor(info) {
Some(ref descriptor) => Some(self.shared.device.lock().new_sampler(descriptor)),
None => None,
},
data: conv::map_sampler_data_to_naga(info),
#[cfg(feature = "cross")]
data: Self::make_sampler_data(&info),
cross_data: conv::map_sampler_data_to_cross(info),
})
}
@ -2126,17 +2245,26 @@ impl hal::device::Device<Backend> for Device {
let usage = n::ArgumentArray::describe_usage(desc.ty);
let bind_target = naga::back::msl::BindTarget {
buffer: if content.contains(n::DescriptorContent::BUFFER) {
Some(arguments.push(metal::MTLDataType::Pointer, desc.count, usage) as u8)
Some(
arguments.push(metal::MTLDataType::Pointer, desc.count, usage)
as naga::back::msl::Slot,
)
} else {
None
},
texture: if content.contains(n::DescriptorContent::TEXTURE) {
Some(arguments.push(metal::MTLDataType::Texture, desc.count, usage) as u8)
Some(
arguments.push(metal::MTLDataType::Texture, desc.count, usage)
as naga::back::msl::Slot,
)
} else {
None
},
sampler: if content.contains(n::DescriptorContent::SAMPLER) {
Some(arguments.push(metal::MTLDataType::Sampler, desc.count, usage) as u8)
let slot = arguments.push(metal::MTLDataType::Sampler, desc.count, usage);
Some(naga::back::msl::BindSamplerTarget::Resource(
slot as naga::back::msl::Slot,
))
} else {
None
},
@ -2145,7 +2273,10 @@ impl hal::device::Device<Backend> for Device {
let res_offset = bind_target
.buffer
.or(bind_target.texture)
.or(bind_target.sampler)
.or(bind_target.sampler.as_ref().and_then(|bst| match *bst {
naga::back::msl::BindSamplerTarget::Resource(slot) => Some(slot),
naga::back::msl::BindSamplerTarget::Inline(_) => None,
}))
.unwrap() as u32;
bindings.insert(
desc.binding,
@ -2192,8 +2323,9 @@ impl hal::device::Device<Backend> for Device {
.enumerate()
.map(|(array_index, sm)| TempSampler {
data: n::ImmutableSampler {
data: sm.data.clone(),
#[cfg(feature = "cross")]
cross_data: sm.data.clone(),
cross_data: sm.cross_data.clone(),
},
binding: slb.binding,
array_index,
@ -2915,6 +3047,7 @@ impl hal::device::Device<Backend> for Device {
kind: image::ViewKind,
format: format::Format,
swizzle: format::Swizzle,
_usage: image::Usage,
range: image::SubresourceRange,
) -> Result<n::ImageView, image::ViewCreationError> {
let mtl_format = match self

Просмотреть файл

@ -69,6 +69,7 @@ use cocoa_foundation::foundation::NSInteger;
use dispatch;
use foreign_types::ForeignTypeRef;
use metal::MTLFeatureSet;
use metal::MTLGPUFamily;
use metal::MTLLanguageVersion;
use metal::{CGFloat, CGSize, MetalLayer, MetalLayerRef};
use objc::{
@ -91,6 +92,8 @@ mod conversions;
mod device;
mod internal;
mod native;
#[cfg(feature = "pipeline-cache")]
mod pipeline_cache;
mod soft;
mod window;
@ -746,6 +749,7 @@ struct PrivateCapabilities {
max_total_threadgroup_memory: u32,
sample_count_mask: u8,
supports_debug_markers: bool,
supports_binary_archives: bool,
}
impl PrivateCapabilities {
@ -1042,6 +1046,8 @@ impl PrivateCapabilities {
MTLFeatureSet::tvOS_GPUFamily2_v1,
],
),
supports_binary_archives: device.supports_family(MTLGPUFamily::Apple3)
|| device.supports_family(MTLGPUFamily::Mac1),
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше