Dawn/Native: Implement SetImmediateData() in D3D11 Backend

This CL implement SetImmediateData() API in D3D11 backend. User
could use SetImmediateData() in renderPass/ComputePass to upload
small constants.

Bug:366291600
Change-Id: I892de39c578db4bf551f8c3dbb426154279ba387
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/244097
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Quyen Le <lehoangquyen@chromium.org>
Commit-Queue: Shaobo Yan <shaoboyan@microsoft.com>
diff --git a/src/dawn/native/ProgrammableEncoder.cpp b/src/dawn/native/ProgrammableEncoder.cpp
index 219d5cd..9a4ea58 100644
--- a/src/dawn/native/ProgrammableEncoder.cpp
+++ b/src/dawn/native/ProgrammableEncoder.cpp
@@ -36,6 +36,7 @@
 #include "dawn/native/Commands.h"
 #include "dawn/native/Device.h"
 #include "dawn/native/ObjectType_autogen.h"
+#include "dawn/native/PhysicalDevice.h"
 #include "dawn/native/ValidationUtils_autogen.h"
 #include "dawn/native/utils/WGPUHelpers.h"
 
@@ -136,6 +137,14 @@
                 DAWN_INVALID_IF(size > maxImmediateSize - offset,
                                 "offset (%u) + size (%u): is larger than maxImmediateSize (%u).",
                                 offset, size, maxImmediateSize);
+                if (GetDevice()->GetPhysicalDevice()->GetBackendType() ==
+                        wgpu::BackendType::D3D11 ||
+                    GetDevice()->GetPhysicalDevice()->GetBackendType() ==
+                        wgpu::BackendType::D3D12) {
+                    const bool useTintIR = GetDevice()->IsToggleEnabled(Toggle::UseTintIR);
+                    DAWN_INVALID_IF(!useTintIR,
+                                    "SetImmediateData should not be used without tint ir.");
+                }
             }
 
             // Skip SetImmediateData when uploading constants are empty.
diff --git a/src/dawn/native/d3d11/CommandBufferD3D11.cpp b/src/dawn/native/d3d11/CommandBufferD3D11.cpp
index 97e7388..5d2c2d9 100644
--- a/src/dawn/native/d3d11/CommandBufferD3D11.cpp
+++ b/src/dawn/native/d3d11/CommandBufferD3D11.cpp
@@ -616,8 +616,14 @@
                 break;
             }
 
-            case Command::SetImmediateData:
-                return DAWN_UNIMPLEMENTED_ERROR("SetImmediateData unimplemented");
+            case Command::SetImmediateData: {
+                SetImmediateDataCmd* cmd = mCommands.NextCommand<SetImmediateDataCmd>();
+                DAWN_ASSERT(cmd->size > 0);
+                uint8_t* value = nullptr;
+                value = mCommands.NextData<uint8_t>(cmd->size);
+                immediates.SetImmediateData(cmd->offset, value, cmd->size);
+                break;
+            }
 
             default:
                 DAWN_UNREACHABLE();
@@ -869,6 +875,15 @@
                 break;
             }
 
+            case Command::SetImmediateData: {
+                SetImmediateDataCmd* cmd = mCommands.NextCommand<SetImmediateDataCmd>();
+                DAWN_ASSERT(cmd->size > 0);
+                uint8_t* value = nullptr;
+                value = mCommands.NextData<uint8_t>(cmd->size);
+                immediates.SetImmediateData(cmd->offset, value, cmd->size);
+                break;
+            }
+
             default:
                 DAWN_UNREACHABLE();
                 break;
@@ -988,9 +1003,6 @@
             case Command::WriteTimestamp:
                 return DAWN_UNIMPLEMENTED_ERROR("WriteTimestamp unimplemented");
 
-            case Command::SetImmediateData:
-                return DAWN_UNIMPLEMENTED_ERROR("SetImmediateData unimplemented");
-
             default: {
                 DAWN_TRY(DoRenderBundleCommand(&mCommands, type));
             }
diff --git a/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp b/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
index 26019d0..1fdc0d5 100644
--- a/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
+++ b/src/dawn/native/d3d11/CommandRecordingContextD3D11.cpp
@@ -216,6 +216,8 @@
                                                       1, &bufferPtr);
     Get()->mD3D11DeviceContext3->CSSetConstantBuffers(PipelineLayout::kReservedConstantBufferSlot,
                                                       1, &bufferPtr);
+    Get()->mD3D11DeviceContext3->PSSetConstantBuffers(PipelineLayout::kReservedConstantBufferSlot,
+                                                      1, &bufferPtr);
 
     return {};
 }
diff --git a/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp b/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
index 0bb0b5f..87c00c8 100644
--- a/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
+++ b/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
@@ -292,6 +292,8 @@
     // See the discussions in https://github.com/gpuweb/gpuweb/issues/1962 for more details.
     limits->v1.maxInterStageShaderVariables = D3D11_PS_INPUT_REGISTER_COUNT - 2;
 
+    limits->v1.maxImmediateSize = kDefaultMaxImmediateDataBytes;
+
     // The BlitTextureToBuffer helper requires the alignment to be 4.
     limits->texelCopyBufferRowAlignmentLimits.minTexelCopyBufferRowAlignment = 4;
 
diff --git a/src/dawn/tests/end2end/ImmediateDataTests.cpp b/src/dawn/tests/end2end/ImmediateDataTests.cpp
index 5555971..f770490 100644
--- a/src/dawn/tests/end2end/ImmediateDataTests.cpp
+++ b/src/dawn/tests/end2end/ImmediateDataTests.cpp
@@ -485,7 +485,7 @@
     }
 }
 
-DAWN_INSTANTIATE_TEST(ImmediateDataTests, VulkanBackend());
+DAWN_INSTANTIATE_TEST(ImmediateDataTests, D3D11Backend({"use_tint_ir"}), VulkanBackend());
 
 }  // anonymous namespace
 }  // namespace dawn
diff --git a/src/dawn/tests/unittests/validation/ImmediateDataTests.cpp b/src/dawn/tests/unittests/validation/ImmediateDataTests.cpp
index 123f8dd..9b40299 100644
--- a/src/dawn/tests/unittests/validation/ImmediateDataTests.cpp
+++ b/src/dawn/tests/unittests/validation/ImmediateDataTests.cpp
@@ -38,7 +38,10 @@
 namespace dawn {
 namespace {
 
-class ImmediateDataDisableTest : public ValidationTest {};
+class ImmediateDataDisableTest : public ValidationTest {
+  protected:
+    std::vector<const char*> GetEnabledToggles() override { return {"use_tint_ir"}; }
+};
 
 // Check that creating a PipelineLayout with non-zero immediateSize is disallowed
 // without the feature enabled.
@@ -77,6 +80,8 @@
         required.maxImmediateSize = kDefaultMaxImmediateDataBytes;
     }
 
+    std::vector<const char*> GetEnabledToggles() override { return {"use_tint_ir"}; }
+
     wgpu::BindGroupLayout CreateBindGroupLayout() {
         wgpu::BindGroupLayoutEntry entries[1];
         entries[0].binding = 0;