[clang] [llvm] [HLSL][SPIR-V] Implement vk::push_constant (PR #166793)
Nathan Gauër via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 11 07:00:26 PST 2025
================
@@ -0,0 +1,108 @@
+//===- SPIRVPushConstantAccess.cpp - Translate CBuffer Loads ---------*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass changes the types of all the globals in the PushConstant
+// address space into a target extension type, and makes all references
+// to this global go though a custom SPIR-V intrinsic.
+//
+// This allows the backend to properly lower the push constant struct type
+// to a fully laid out type, and generate the proper OpAccessChain.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVPushConstantAccess.h"
+#include "SPIRV.h"
+#include "SPIRVSubtarget.h"
+#include "SPIRVTargetMachine.h"
+#include "SPIRVUtils.h"
+#include "llvm/Frontend/HLSL/CBuffer.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/ReplaceConstant.h"
+
+#define DEBUG_TYPE "spirv-pushconstant-access"
+using namespace llvm;
+
+static bool replacePushConstantAccesses(Module &M, SPIRVGlobalRegistry *GR) {
+ SmallVector<GlobalVariable *> PushConstants;
+ for (GlobalVariable &GV : M.globals()) {
+ if (GV.getAddressSpace() ==
+ storageClassToAddressSpace(SPIRV::StorageClass::PushConstant))
+ PushConstants.push_back(&GV);
+ }
+
+ for (GlobalVariable *GV : PushConstants) {
+ Type *PCType = llvm::TargetExtType::get(
+ M.getContext(), "spirv.PushConstant", {GV->getValueType()});
+ GlobalVariable *NewGV = new GlobalVariable(
+ M, PCType, GV->isConstant(), GV->getLinkage(),
+ /* initializer= */ nullptr, GV->getName(),
+ /* InsertBefore= */ GV, GV->getThreadLocalMode(), GV->getAddressSpace(),
+ GV->isExternallyInitialized());
+
+ SmallVector<User *, 4> Users(GV->user_begin(), GV->user_end());
+ for (llvm::User *U : Users) {
+ Instruction *I = dyn_cast<Instruction>(U);
+ if (!I)
+ continue;
----------------
Keenuts wrote:
Good question, and I am note sure!
If you take the module as ISelPrepare and dump it, you have your globals and a few uses.
But if you iterate over the global uses, you'll find what looks like inline operands, but which are not visible in the module dump.
Those are not visible in any `print-before-all`/`print-after-all` dump.
https://github.com/llvm/llvm-project/pull/166793
More information about the llvm-commits
mailing list