mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-04-20 00:14:45 +00:00
Generate CUDA types ahead of time
This commit is contained in:
parent
6d8819f2fa
commit
fa94cdfc16
13 changed files with 8311 additions and 4840 deletions
48
Cargo.toml
48
Cargo.toml
|
@ -1,24 +1,24 @@
|
|||
[workspace]
|
||||
|
||||
resolver = "2"
|
||||
|
||||
members = [
|
||||
"ext/hip_runtime-sys",
|
||||
"ext/amd_comgr-sys",
|
||||
"comgr",
|
||||
"cuda_base",
|
||||
"cuda_types",
|
||||
"detours-sys",
|
||||
"zluda",
|
||||
"zluda_dump",
|
||||
"zluda_lib",
|
||||
"zluda_inject",
|
||||
"zluda_redirect",
|
||||
"zluda_ml",
|
||||
"ptx",
|
||||
"ptx_parser",
|
||||
"ptx_parser_macros",
|
||||
"ptx_parser_macros_impl",
|
||||
]
|
||||
|
||||
default-members = ["zluda_lib", "zluda_ml", "zluda_inject", "zluda_redirect"]
|
||||
[workspace]
|
||||
|
||||
resolver = "2"
|
||||
|
||||
members = [
|
||||
"ext/hip_runtime-sys",
|
||||
"ext/amd_comgr-sys",
|
||||
"comgr",
|
||||
"cuda_base",
|
||||
"cuda_types",
|
||||
"detours-sys",
|
||||
"zluda",
|
||||
"zluda_dump",
|
||||
"zluda_inject",
|
||||
"zluda_redirect",
|
||||
"zluda_ml",
|
||||
"ptx",
|
||||
"ptx_parser",
|
||||
"ptx_parser_macros",
|
||||
"ptx_parser_macros_impl",
|
||||
"zluda_bindgen",
|
||||
]
|
||||
|
||||
default-members = ["zluda", "zluda_ml", "zluda_inject", "zluda_redirect"]
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,13 +2,15 @@
|
|||
name = "zluda"
|
||||
version = "0.0.0"
|
||||
authors = ["Andrzej Janik <vosen@vosen.pl>"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "zluda"
|
||||
name = "nvcuda"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
ptx = { path = "../ptx" }
|
||||
cuda_types = { path = "../cuda_types" }
|
||||
hip_runtime-sys = { path = "../ext/hip_runtime-sys" }
|
||||
lazy_static = "1.4"
|
||||
num_enum = "0.4"
|
||||
|
@ -16,12 +18,5 @@ lz4-sys = "1.9"
|
|||
tempfile = "3"
|
||||
paste = "1.0"
|
||||
|
||||
[dependencies.ocl-core]
|
||||
version = "0.11"
|
||||
features = ["opencl_version_1_2", "opencl_version_2_0", "opencl_version_2_1"]
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["heapapi", "std"] }
|
||||
|
||||
[dev-dependencies]
|
||||
cuda-driver-sys = "0.3.0"
|
|
@ -1,20 +0,0 @@
|
|||
use env::VarError;
|
||||
use std::{env, path::PathBuf};
|
||||
|
||||
// HACK ALERT
|
||||
// This is a temporary hack to to make sure that linker does not pick up
|
||||
// NVIDIA OpenCL .lib using paths injected by cl-sys
|
||||
|
||||
fn main() -> Result<(), VarError> {
|
||||
if cfg!(windows) {
|
||||
let env = env::var("CARGO_CFG_TARGET_ENV")?;
|
||||
if env == "msvc" {
|
||||
let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?);
|
||||
path.push("lib");
|
||||
println!("cargo:rustc-link-search=native={}", path.display());
|
||||
} else {
|
||||
println!("cargo:rustc-link-search=native=C:\\Windows\\System32");
|
||||
};
|
||||
}
|
||||
Ok(())
|
||||
}
|
4720
zluda/src/cuda.rs
4720
zluda/src/cuda.rs
File diff suppressed because it is too large
Load diff
|
@ -1,53 +1,41 @@
|
|||
use std::{ffi::c_void, mem, ptr};
|
||||
|
||||
use hip_runtime_sys::{hipError_t, hipMemoryType, hipPointerGetAttributes};
|
||||
|
||||
use crate::{
|
||||
cuda::{CUdeviceptr, CUmemorytype, CUpointer_attribute},
|
||||
hip_call,
|
||||
};
|
||||
use cuda_types::*;
|
||||
use hip_runtime_sys::*;
|
||||
use std::{ffi::c_void, ptr};
|
||||
|
||||
pub(crate) unsafe fn get_attribute(
|
||||
data: *mut c_void,
|
||||
attribute: CUpointer_attribute,
|
||||
ptr: CUdeviceptr,
|
||||
) -> Result<(), hipError_t> {
|
||||
attribute: hipPointer_attribute,
|
||||
ptr: hipDeviceptr_t,
|
||||
) -> CUresult {
|
||||
if data == ptr::null_mut() {
|
||||
return Err(hipError_t::hipErrorInvalidValue);
|
||||
return CUresult::ERROR_INVALID_VALUE;
|
||||
}
|
||||
let mut attribs = mem::zeroed();
|
||||
hip_call! { hipPointerGetAttributes(&mut attribs, ptr.0 as _) };
|
||||
match attribute {
|
||||
CUpointer_attribute::CU_POINTER_ATTRIBUTE_CONTEXT => {
|
||||
*(data as *mut _) = attribs.device;
|
||||
Ok(())
|
||||
}
|
||||
CUpointer_attribute::CU_POINTER_ATTRIBUTE_MEMORY_TYPE => {
|
||||
*(data as *mut _) = memory_type(attribs.memoryType)?;
|
||||
Ok(())
|
||||
}
|
||||
CUpointer_attribute::CU_POINTER_ATTRIBUTE_DEVICE_POINTER => {
|
||||
*(data as *mut _) = attribs.devicePointer;
|
||||
Ok(())
|
||||
}
|
||||
CUpointer_attribute::CU_POINTER_ATTRIBUTE_HOST_POINTER => {
|
||||
*(data as *mut _) = attribs.hostPointer;
|
||||
Ok(())
|
||||
}
|
||||
CUpointer_attribute::CU_POINTER_ATTRIBUTE_IS_MANAGED => {
|
||||
*(data as *mut _) = attribs.isManaged;
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(hipError_t::hipErrorNotSupported),
|
||||
// TODO: implement by getting device ordinal & allocation start,
|
||||
// then go through every context for that device
|
||||
if attribute == hipPointer_attribute::HIP_POINTER_ATTRIBUTE_CONTEXT {
|
||||
return CUresult::ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
if attribute == hipPointer_attribute::HIP_POINTER_ATTRIBUTE_MEMORY_TYPE {
|
||||
let mut hip_result = hipMemoryType(0);
|
||||
hipPointerGetAttribute(
|
||||
(&mut hip_result as *mut hipMemoryType).cast::<c_void>(),
|
||||
attribute,
|
||||
ptr,
|
||||
)?;
|
||||
let cuda_result = memory_type(hip_result)?;
|
||||
*(data as _) = cuda_result;
|
||||
} else {
|
||||
hipPointerGetAttribute(data, attribute, ptr)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn memory_type(cu: hipMemoryType) -> Result<CUmemorytype, hipError_t> {
|
||||
fn memory_type(cu: hipMemoryType) -> Result<CUmemorytype, hipErrorCode_t> {
|
||||
match cu {
|
||||
hipMemoryType::hipMemoryTypeHost => Ok(CUmemorytype::CU_MEMORYTYPE_HOST),
|
||||
hipMemoryType::hipMemoryTypeDevice => Ok(CUmemorytype::CU_MEMORYTYPE_DEVICE),
|
||||
hipMemoryType::hipMemoryTypeArray => Ok(CUmemorytype::CU_MEMORYTYPE_ARRAY),
|
||||
hipMemoryType::hipMemoryTypeUnified => Ok(CUmemorytype::CU_MEMORYTYPE_UNIFIED),
|
||||
_ => Err(hipError_t::hipErrorInvalidValue),
|
||||
_ => Err(hipErrorCode_t::hipErrorInvalidValue),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[cfg(test)]
|
||||
extern crate cuda_driver_sys;
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate paste;
|
||||
extern crate ptx;
|
||||
|
||||
|
|
11
zluda_bindgen/Cargo.toml
Normal file
11
zluda_bindgen/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "zluda_bindgen"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bindgen = "0.70"
|
||||
syn = { version = "2.0", features = ["full", "visit-mut"] }
|
||||
proc-macro2 = "1.0.89"
|
||||
quote = "1.0"
|
||||
prettyplease = "0.2.25"
|
7
zluda_bindgen/build/cuda_wrapper.h
Normal file
7
zluda_bindgen/build/cuda_wrapper.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#define __CUDA_API_VERSION_INTERNAL
|
||||
#include <cuda.h>
|
||||
#include <cudaProfiler.h>
|
||||
#include <cudaGL.h>
|
||||
#include <cudaEGL.h>
|
||||
#include <vdpau/vdpau.h>
|
||||
#include <cudaVDPAU.h>
|
156
zluda_bindgen/src/main.rs
Normal file
156
zluda_bindgen/src/main.rs
Normal file
|
@ -0,0 +1,156 @@
|
|||
use proc_macro2::Span;
|
||||
use quote::{format_ident, quote};
|
||||
use std::{path::PathBuf, str::FromStr};
|
||||
use syn::{
|
||||
parse_quote, punctuated::Punctuated, visit_mut::VisitMut, Abi, Item, ItemUse, LitStr, UseTree,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let crate_root = PathBuf::from_str(env!("CARGO_MANIFEST_DIR")).unwrap();
|
||||
let cuda_header = bindgen::Builder::default()
|
||||
.use_core()
|
||||
.header_contents("cuda_wrapper.h", include_str!("../build/cuda_wrapper.h"))
|
||||
.no_partialeq("CUDA_HOST_NODE_PARAMS_st")
|
||||
.derive_eq(true)
|
||||
.allowlist_type("^CU.*")
|
||||
.allowlist_function("^cu.*")
|
||||
.allowlist_var("^CU.*")
|
||||
.default_enum_style(bindgen::EnumVariation::NewType {
|
||||
is_bitfield: false,
|
||||
is_global: false,
|
||||
})
|
||||
.layout_tests(false)
|
||||
.new_type_alias(r"^CUdevice_v\d+$")
|
||||
.new_type_alias(r"^CUdeviceptr_v\d+$")
|
||||
.must_use_type("cudaError_enum")
|
||||
.constified_enum("cudaError_enum")
|
||||
.clang_args(["-I/usr/local/cuda/include"])
|
||||
.generate()
|
||||
.unwrap()
|
||||
.to_string();
|
||||
generate_types(
|
||||
crate_root,
|
||||
&["..", "cuda_types", "src", "lib.rs"],
|
||||
cuda_header,
|
||||
);
|
||||
}
|
||||
|
||||
fn generate_types(mut output: PathBuf, path: &[&str], cuda_header: String) {
|
||||
let mut module: syn::File = syn::parse_str(&cuda_header).unwrap();
|
||||
module.attrs.push(parse_quote! {
|
||||
#![allow(warnings)]
|
||||
});
|
||||
let mut converter = ConvertIntoRustResult {
|
||||
type_: "CUresult",
|
||||
underlying_type: "cudaError_enum",
|
||||
new_error_type: "CUerror",
|
||||
error_prefix: ("CUDA_ERROR", "ERROR"),
|
||||
success: ("CUDA_SUCCESS", "SUCCESS"),
|
||||
constants: Vec::new(),
|
||||
};
|
||||
module.items = module
|
||||
.items
|
||||
.into_iter()
|
||||
.filter_map(|item| match item {
|
||||
Item::ForeignMod(_) => None,
|
||||
Item::Const(const_) => converter.get_const(const_).map(Item::Const),
|
||||
Item::Use(use_) => converter.get_use(use_).map(Item::Use),
|
||||
item => Some(item),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
converter.flush(&mut module.items);
|
||||
syn::visit_mut::visit_file_mut(&mut FixAbi, &mut module);
|
||||
for segment in path {
|
||||
output.push(segment);
|
||||
}
|
||||
std::fs::write(output, prettyplease::unparse(&module)).unwrap();
|
||||
}
|
||||
|
||||
struct ConvertIntoRustResult {
|
||||
type_: &'static str,
|
||||
underlying_type: &'static str,
|
||||
new_error_type: &'static str,
|
||||
error_prefix: (&'static str, &'static str),
|
||||
success: (&'static str, &'static str),
|
||||
constants: Vec<syn::ItemConst>,
|
||||
}
|
||||
|
||||
impl ConvertIntoRustResult {
|
||||
fn get_const(&mut self, const_: syn::ItemConst) -> Option<syn::ItemConst> {
|
||||
let name = const_.ident.to_string();
|
||||
if name.starts_with(self.underlying_type) {
|
||||
self.constants.push(const_);
|
||||
None
|
||||
} else {
|
||||
Some(const_)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_use(&mut self, use_: ItemUse) -> Option<ItemUse> {
|
||||
if let UseTree::Path(ref path) = use_.tree {
|
||||
if let UseTree::Rename(ref rename) = &*path.tree {
|
||||
if rename.rename == self.type_ {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(use_)
|
||||
}
|
||||
|
||||
fn flush(self, items: &mut Vec<Item>) {
|
||||
let type_ = format_ident!("{}", self.type_);
|
||||
let type_trait = format_ident!("{}Consts", self.type_);
|
||||
let new_error_type = format_ident!("{}", self.new_error_type);
|
||||
let success = format_ident!("{}", self.success.1);
|
||||
let mut result_variants = Vec::new();
|
||||
let mut error_variants = Vec::new();
|
||||
for const_ in self.constants.iter() {
|
||||
let ident = const_.ident.to_string();
|
||||
if ident.ends_with(self.success.0) {
|
||||
result_variants.push(quote! {
|
||||
const #success: #type_ = #type_::Ok(());
|
||||
});
|
||||
} else {
|
||||
let old_prefix_len = self.underlying_type.len() + 1 + self.error_prefix.0.len() + 1;
|
||||
let variant_ident =
|
||||
format_ident!("{}_{}", self.error_prefix.1, &ident[old_prefix_len..]);
|
||||
let error_ident = format_ident!("{}", &ident[old_prefix_len..]);
|
||||
let expr = &const_.expr;
|
||||
result_variants.push(quote! {
|
||||
const #variant_ident: #type_ = #type_::Err(#new_error_type::#error_ident);
|
||||
});
|
||||
error_variants.push(quote! {
|
||||
pub const #error_ident: #new_error_type = #new_error_type(unsafe { ::core::num::NonZeroU32::new_unchecked(#expr) });
|
||||
});
|
||||
}
|
||||
}
|
||||
let extra_items: Punctuated<syn::Item, syn::parse::Nothing> = parse_quote! {
|
||||
impl #new_error_type {
|
||||
#(#error_variants)*
|
||||
}
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct #new_error_type(pub ::core::num::NonZeroU32);
|
||||
pub trait #type_trait {
|
||||
#(#result_variants)*
|
||||
}
|
||||
impl #type_trait for #type_ {}
|
||||
#[must_use]
|
||||
pub type #type_ = ::core::result::Result<(), #new_error_type>;
|
||||
const _: fn() = || {
|
||||
let _ = std::mem::transmute::<#type_, u32>;
|
||||
};
|
||||
};
|
||||
items.extend(extra_items);
|
||||
}
|
||||
}
|
||||
|
||||
struct FixAbi;
|
||||
|
||||
impl VisitMut for FixAbi {
|
||||
fn visit_abi_mut(&mut self, i: &mut Abi) {
|
||||
if let Some(ref mut name) = i.name {
|
||||
*name = LitStr::new("system", Span::call_site());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
[package]
|
||||
name = "zluda_lib"
|
||||
version = "0.0.0"
|
||||
authors = ["Andrzej Janik <vosen@vosen.pl>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "nvcuda"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
zluda = { path = "../zluda" }
|
|
@ -1 +0,0 @@
|
|||
This project exist solely as a workaround, to make sure that ZLUDA-created CUDA driver does not clash with real CUDA driver when running unit tests
|
|
@ -1,11 +0,0 @@
|
|||
pub extern crate zluda;
|
||||
|
||||
pub use zluda::cuda::*;
|
||||
|
||||
// For some reason, on Linux linker strips out all our re-exports,
|
||||
// there's probably a cleaner solution, but for now just exporting
|
||||
// the function below stops it from doing so
|
||||
#[no_mangle]
|
||||
fn _zluda_very_bad_linker_hack() {
|
||||
cuInit(0);
|
||||
}
|
Loading…
Add table
Reference in a new issue