зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
274b1a8f6e
Коммит
cdb4fe1fcb
|
@ -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"
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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/ash/src/extensions/ext/debug_marker.rs
поставляемый
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_report.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/android_surface.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/display_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/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/win32_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/khr/xlib_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/mvk/macos_surface.rs
поставляемый
Normal file → Executable file
0
third_party/rust/cubeb-coreaudio/install_rustfmt_clippy.sh
поставляемый
Normal file → Executable file
0
third_party/rust/cubeb-coreaudio/install_rustfmt_clippy.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/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/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/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/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/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.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/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_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_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_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_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_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_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_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_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_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_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_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_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_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_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/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/cubeb-sys/libcubeb/scan-build-install.sh
поставляемый
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}
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче