From 85892416485f48655c6808a06961b83cb4176915 Mon Sep 17 00:00:00 2001 From: "nv-slang-bot[bot]" <274397474+nv-slang-bot[bot]@users.noreply.github.com> Date: Sun, 12 Jul 2026 18:45:19 +0000 Subject: [PATCH 1/3] test: failing regression for mixed requires_grad IDiffTensor backward (#1056) Two IDiffTensor inputs to a [Differentiable] fn abort with CUDA_ERROR_ILLEGAL_ADDRESS in backward when only some inputs have requires_grad=True. Covers yes/yes, yes/no, no/yes under both torch bridge modes. --- .../slangpy_tests/test_torchintegration.py | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/slangpy/tests/slangpy_tests/test_torchintegration.py b/slangpy/tests/slangpy_tests/test_torchintegration.py index a8d6d8afc..7eb7f3f5f 100644 --- a/slangpy/tests/slangpy_tests/test_torchintegration.py +++ b/slangpy/tests/slangpy_tests/test_torchintegration.py @@ -649,6 +649,54 @@ def test_null_grad_idifftensor(device_type: DeviceType): loss.backward() +@pytest.mark.parametrize("device_type", DEVICE_TYPES) +@pytest.mark.parametrize("a_grad,b_grad", [(True, True), (True, False), (False, True)]) +def test_mixed_requires_grad_idifftensor(device_type: DeviceType, a_grad: bool, b_grad: bool): + """ + Regression for shader-slang/slangpy#1056. + + A [Differentiable] function with two IDiffTensor inputs aborts the process with + CUDA_ERROR_ILLEGAL_ADDRESS during backward when only some inputs have + requires_grad=True. The compiled backward kernel scatters _grad_out + unconditionally for every IDiffTensor param, but dispatch only bound a grad + buffer for requires_grad=True inputs, leaving the other's _grad_out a dangling + device pointer that the atomic scatter faults on. yes/yes worked; yes/no and + no/yes aborted. The autouse torch_bridge_mode fixture exercises both bridge paths. + """ + src = """ +import slangpy; + +[Differentiable] +void mul2(uint index, IDiffTensor a, IDiffTensor b, IWDiffTensor out) +{ + out[index] = a[index] * b[index]; +} +""" + import torch + + device = helpers.get_torch_device(device_type) + module = helpers.create_module(device, src) + + a = torch.tensor([1.0, 2.0, 3.0, 4.0], dtype=torch.float32, device="cuda", requires_grad=a_grad) + b = torch.tensor([5.0, 6.0, 7.0, 8.0], dtype=torch.float32, device="cuda", requires_grad=b_grad) + out = torch.zeros(size=(4,), dtype=torch.float32, device="cuda", requires_grad=True) + + module.mul2(index=grid(shape=(4,)), a=a, b=b, out=out) + out.sum().backward() + + # sum(a * b): d/da = b, d/db = a. torch reports .grad only for requires_grad leaves. + if a_grad: + assert a.grad is not None + compare_tensors(b.detach(), a.grad) + else: + assert a.grad is None + if b_grad: + assert b.grad is not None + compare_tensors(a.detach(), b.grad) + else: + assert b.grad is None + + @pytest.mark.parametrize("device_type", DEVICE_TYPES) def test_nn_parameter_as_input(device_type: DeviceType): """ From 275253ead79ec672e2e4590ffe8f25c0bde49d8e Mon Sep 17 00:00:00 2001 From: "nv-slang-bot[bot]" <274397474+nv-slang-bot[bot]@users.noreply.github.com> Date: Sun, 12 Jul 2026 19:35:58 +0000 Subject: [PATCH 2/3] fix: bind grad buffer for no-grad IDiffTensor inputs in backward (#1056) A [Differentiable] function with multiple IDiffTensor inputs called through the torch integration aborted the process with CUDA_ERROR_ILLEGAL_ADDRESS during backward when only some inputs had requires_grad=True. Every IDiffTensor param binds as a DiffTensor in the backward pass, so the compiled kernel scatters into its _grad_out unconditionally, but dispatch only allocated a grad buffer for requires_grad=True inputs. On CUDA the atomic scatter targets a raw device pointer, so the no-grad input's unbound _grad_out faulted; on other backends type resolution rejects a diff tensor with no output gradient outright. Bind a throwaway zeroed buffer for no-grad differentiable inputs so the scatter lands in valid memory. The buffer is discarded and None is still returned to torch for that leaf, so autograd reports no gradient for it. Closes #1056 --- src/slangpy_ext/utils/slangpy.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/slangpy_ext/utils/slangpy.cpp b/src/slangpy_ext/utils/slangpy.cpp index ca4be81d0..ac048ff23 100644 --- a/src/slangpy_ext/utils/slangpy.cpp +++ b/src/slangpy_ext/utils/slangpy.cpp @@ -572,7 +572,16 @@ nb::tuple NativeCallData::autograd_backward( pair->grad = bridge.create_zeros_like_tensor(pair->primal); input_grads.append(pair->grad); } else { - pair->grad = nb::none(); + // An IDiffTensor input always binds as a DiffTensor in the backward pass, so it + // needs an output-gradient buffer regardless of whether this leaf wants a + // gradient: on CUDA the compiled kernel scatters into _grad_out through a raw + // device pointer, so an unbound buffer is a dangling pointer the atomic write + // faults on (CUDA_ERROR_ILLEGAL_ADDRESS, #1056); on other backends type + // resolution rejects a diff tensor with no associated output gradient outright + // (tensorcommon.py). Bind a throwaway zeroed buffer so both paths are satisfied; + // it is discarded - torch still sees no gradient for this leaf via the None + // appended below. + pair->grad = bridge.create_zeros_like_tensor(pair->primal); input_grads.append(nb::none()); } } else { From a541eeb2d23e8515506683885b63cae8a31d686f Mon Sep 17 00:00:00 2001 From: "nv-slang-bot[bot]" <274397474+nv-slang-bot[bot]@users.noreply.github.com> Date: Sun, 12 Jul 2026 20:03:07 +0000 Subject: [PATCH 3/3] =?UTF-8?q?test:=20clarify=20#1056=20docstring=20?= =?UTF-8?q?=E2=80=94=20backend-specific=20pre-fix=20failure=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On CUDA the pre-fix failure aborts the process (illegal address); on other backends type resolution rejects the unbound gradient with a TypeError. Addresses reviewer clarity nit on PR #1057. --- .../tests/slangpy_tests/test_torchintegration.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/slangpy/tests/slangpy_tests/test_torchintegration.py b/slangpy/tests/slangpy_tests/test_torchintegration.py index 7eb7f3f5f..1944f6b10 100644 --- a/slangpy/tests/slangpy_tests/test_torchintegration.py +++ b/slangpy/tests/slangpy_tests/test_torchintegration.py @@ -655,13 +655,14 @@ def test_mixed_requires_grad_idifftensor(device_type: DeviceType, a_grad: bool, """ Regression for shader-slang/slangpy#1056. - A [Differentiable] function with two IDiffTensor inputs aborts the process with - CUDA_ERROR_ILLEGAL_ADDRESS during backward when only some inputs have - requires_grad=True. The compiled backward kernel scatters _grad_out - unconditionally for every IDiffTensor param, but dispatch only bound a grad - buffer for requires_grad=True inputs, leaving the other's _grad_out a dangling - device pointer that the atomic scatter faults on. yes/yes worked; yes/no and - no/yes aborted. The autouse torch_bridge_mode fixture exercises both bridge paths. + A [Differentiable] function with two IDiffTensor inputs failed during backward + when only some inputs had requires_grad=True. The compiled backward kernel + scatters _grad_out unconditionally for every IDiffTensor param, but dispatch only + bound a grad buffer for requires_grad=True inputs. On CUDA the other input's + _grad_out was a dangling device pointer the atomic scatter faulted on, aborting + the process with CUDA_ERROR_ILLEGAL_ADDRESS; on other backends type resolution + rejected the unbound gradient with a TypeError. yes/yes worked; yes/no and no/yes + failed. The autouse torch_bridge_mode fixture exercises both bridge paths. """ src = """ import slangpy;