Skip to content
Permalink
Browse files
GPU string overhaul (#1531)
* GPU string overhaul

Big string cleanup, yet again, for GPU. We still had this tricky
double indirection happening with strings for OptiX -- the string was
a pointer to a "global", which in turn held the hash. No, throw all
that out.  Just directly store strings as the ustring hash on
OptiX. No extra indirection. Many fewer differences between how things
are handled on OptiX versus CPU (except for the fact itself that the
"string" holds the hash rather than the char*).

Some details worth noting:

* LLVM_Util loses "type_string()" and calls it "type_ustring()" to
  emphasize it's the type we're using to represent a ustring, and
  definitely not a C or C++std string. Also, LLVM_Util itself now lets
  the caller tell it whether it prefers that the representation of a
  ustring be the charptr or the hash, and then handles most of the
  details internally. The BackendLLVM, then, makes that decision early
  on, charptr for CPU and hash for GPU.

* Several more spots in LLVM_Util and BackendLLVM have been plumbed to
  pass around llvm IR SSA variable names to try to make the resulting
  LLVM IR more readable when I'm trying to debug it. (This was
  strictly debugging scaffalding aid for me, but comes along for the
  ride because it's useful to keep.) I also added a
  BackendLLVM::llnamefmt to format strings, which only does the
  formatting when the shading system knows it's going to save the IR
  for inspection, and otherwise (that is, in production) it does not
  do the string formatting or pass the names along, so it's not doing
  all that string manipulation when no human is going to be looking at
  the IR dumps.

* A lot of clunky OptiX-only code disappears.

* Some side effects of my reducing complexity of the IR as I debugged:
  there were times we were generating redundant pointer casting in the
  IR, such as grabbing a pointer, then casting it to a void*, then
  casting back to some other kind of pointer. In some cases I reduced
  that quite a bit. Again, this was mostly just a scramble to make the
  IR more readable while I debugged, but it probably has a minor
  performance gain as well since it reduced somewhat the sheer amount
  of IR we generate and pass to the optimizer and JIT.

Signed-off-by: Larry Gritz <lg@larrygritz.com>

* Remove register_string entirely from RendererServices

Signed-off-by: Larry Gritz <lg@larrygritz.com>

* Remove more register_string remnants

Signed-off-by: Larry Gritz <lg@larrygritz.com>

* comment typo

Signed-off-by: Larry Gritz <lg@larrygritz.com>
  • Loading branch information
lgritz committed Jul 13, 2022
1 parent 8281721 commit 7b4c7cf
Show file tree
Hide file tree
Showing 15 changed files with 314 additions and 482 deletions.
@@ -108,6 +108,12 @@ class OSLEXECPUBLIC LLVM_Util {
void jit_aggressive(bool val) { m_jit_aggressive = val; }
bool jit_aggressive() const { return m_jit_aggressive; }

// Select whether the representation of a ustring is going to be
// the character pointer, or the hash.
enum class UstringRep { charptr, hash };
UstringRep ustring_rep() const { return m_ustring_rep; }
void ustring_rep(UstringRep rep);

/// Return a reference to the current context.
llvm::LLVMContext& context() const { return *m_llvm_context; }

@@ -311,7 +317,7 @@ class OSLEXECPUBLIC LLVM_Util {

/// Create a new LLVM basic block (for the current function) and return
/// its handle.
llvm::BasicBlock* new_basic_block(const std::string& name = std::string());
llvm::BasicBlock* new_basic_block(const std::string& name = {});

/// Save the return block pointer when entering a function. If
/// after==NULL, generate a new basic block for where to go after the
@@ -543,8 +549,8 @@ class OSLEXECPUBLIC LLVM_Util {
llvm::Type* type_triple() const { return m_llvm_type_triple; }
llvm::Type* type_matrix() const { return m_llvm_type_matrix; }
llvm::Type* type_typedesc() const { return m_llvm_type_longlong; }
llvm::Type* type_ustring() { return m_llvm_type_ustring; }
llvm::PointerType* type_void_ptr() const { return m_llvm_type_void_ptr; }
llvm::PointerType* type_string() { return m_llvm_type_char_ptr; }
llvm::PointerType* type_ustring_ptr() const
{
return m_llvm_type_ustring_ptr;
@@ -579,7 +585,11 @@ class OSLEXECPUBLIC LLVM_Util {
llvm::Type* type_wide_triple() const { return m_llvm_type_wide_triple; }
llvm::Type* type_wide_matrix() const { return m_llvm_type_wide_matrix; }
llvm::Type* type_wide_void_ptr() const { return m_llvm_type_wide_void_ptr; }
llvm::Type* type_wide_string() const
llvm::Type* type_wide_ustring() const
{
return m_llvm_type_wide_ustring;
}
llvm::PointerType* type_wide_ustring_ptr() const
{
return m_llvm_type_wide_ustring_ptr;
}
@@ -629,7 +639,7 @@ class OSLEXECPUBLIC LLVM_Util {
bool is_packed = false);

/// Return the llvm::Type that is a pointer to the given llvm type.
llvm::Type* type_ptr(llvm::Type* type);
llvm::PointerType* type_ptr(llvm::Type* type);

/// Return the llvm::Type that is the wide version of the given llvm type
llvm::Type* type_wide(llvm::Type* type);
@@ -687,7 +697,8 @@ class OSLEXECPUBLIC LLVM_Util {
/// If the type specified is NULL, it will make a 'void *'.
llvm::Value* constant_ptr(void* p, llvm::PointerType* type = NULL);

/// Return an llvm::Value holding the given string constant.
/// Return an llvm::Value holding the given string constant (as
/// determined by the ustring_rep).
llvm::Value* constant(ustring s);
llvm::Value* constant(string_view s) { return constant(ustring(s)); }

@@ -1019,9 +1030,10 @@ class OSLEXECPUBLIC LLVM_Util {
IRBuilder& builder();

int m_debug;
bool m_dumpasm = false;
bool m_jit_fma = false;
bool m_jit_aggressive = false;
bool m_dumpasm = false;
bool m_jit_fma = false;
bool m_jit_aggressive = false;
UstringRep m_ustring_rep = UstringRep::charptr;
PerThreadInfo::Impl* m_thread;
llvm::LLVMContext* m_llvm_context;
llvm::Module* m_llvm_module;
@@ -1037,6 +1049,9 @@ class OSLEXECPUBLIC LLVM_Util {
std::vector<llvm::BasicBlock*> m_loop_after_block; // stack for break
std::vector<llvm::BasicBlock*> m_loop_step_block; // stack for continue

// Incrementing serial numbers
int m_next_serial_bb = 0;

llvm::Type* m_llvm_type_float;
llvm::Type* m_llvm_type_double;
llvm::Type* m_llvm_type_int;
@@ -1049,8 +1064,8 @@ class OSLEXECPUBLIC LLVM_Util {
llvm::Type* m_llvm_type_void;
llvm::Type* m_llvm_type_triple;
llvm::Type* m_llvm_type_matrix;
llvm::Type* m_llvm_type_ustring;
llvm::PointerType* m_llvm_type_void_ptr;
llvm::PointerType* m_llvm_type_ustring_ptr;
llvm::PointerType* m_llvm_type_char_ptr;
llvm::PointerType* m_llvm_type_bool_ptr;
llvm::PointerType* m_llvm_type_int_ptr;
@@ -1059,6 +1074,7 @@ class OSLEXECPUBLIC LLVM_Util {
llvm::PointerType* m_llvm_type_triple_ptr;
llvm::PointerType* m_llvm_type_matrix_ptr;
llvm::PointerType* m_llvm_type_double_ptr;
llvm::PointerType* m_llvm_type_ustring_ptr;

int m_vector_width;
llvm::Type* m_llvm_type_wide_float;
@@ -1070,11 +1086,12 @@ class OSLEXECPUBLIC LLVM_Util {
llvm::Type* m_llvm_type_wide_triple;
llvm::Type* m_llvm_type_wide_matrix;
llvm::Type* m_llvm_type_wide_void_ptr;
llvm::Type* m_llvm_type_wide_ustring_ptr;
llvm::Type* m_llvm_type_wide_ustring;
llvm::PointerType* m_llvm_type_wide_char_ptr;
llvm::PointerType* m_llvm_type_wide_int_ptr;
llvm::PointerType* m_llvm_type_wide_bool_ptr;
llvm::PointerType* m_llvm_type_wide_float_ptr;
llvm::PointerType* m_llvm_type_wide_ustring_ptr;
llvm::Type* m_llvm_type_native_mask;

bool m_supports_masked_stores = false;
@@ -405,15 +405,6 @@ class OSLEXECPUBLIC RendererServices {
/// Return a pointer to the texture system (if available).
virtual TextureSystem *texturesys () const;

/// Register a string with the renderer, so that the renderer can arrange
/// to make the string available in GPU memory as needed. Optionally specify
/// a variable name to associate with the string value.
virtual uint64_t register_string (const std::string& str,
const std::string& var_name)
{
return 0;
}

virtual uint64_t register_global (const std::string& var_name,
uint64_t value)
{

0 comments on commit 7b4c7cf

Please sign in to comment.