mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-08-05 15:49:24 +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
|
@ -11,7 +11,6 @@ members = [
|
||||||
"detours-sys",
|
"detours-sys",
|
||||||
"zluda",
|
"zluda",
|
||||||
"zluda_dump",
|
"zluda_dump",
|
||||||
"zluda_lib",
|
|
||||||
"zluda_inject",
|
"zluda_inject",
|
||||||
"zluda_redirect",
|
"zluda_redirect",
|
||||||
"zluda_ml",
|
"zluda_ml",
|
||||||
|
@ -19,6 +18,7 @@ members = [
|
||||||
"ptx_parser",
|
"ptx_parser",
|
||||||
"ptx_parser_macros",
|
"ptx_parser_macros",
|
||||||
"ptx_parser_macros_impl",
|
"ptx_parser_macros_impl",
|
||||||
|
"zluda_bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = ["zluda_lib", "zluda_ml", "zluda_inject", "zluda_redirect"]
|
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"
|
name = "zluda"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
authors = ["Andrzej Janik <vosen@vosen.pl>"]
|
authors = ["Andrzej Janik <vosen@vosen.pl>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "zluda"
|
name = "nvcuda"
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ptx = { path = "../ptx" }
|
ptx = { path = "../ptx" }
|
||||||
|
cuda_types = { path = "../cuda_types" }
|
||||||
hip_runtime-sys = { path = "../ext/hip_runtime-sys" }
|
hip_runtime-sys = { path = "../ext/hip_runtime-sys" }
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
num_enum = "0.4"
|
num_enum = "0.4"
|
||||||
|
@ -16,12 +18,5 @@ lz4-sys = "1.9"
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
paste = "1.0"
|
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]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = { version = "0.3", features = ["heapapi", "std"] }
|
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 cuda_types::*;
|
||||||
|
use hip_runtime_sys::*;
|
||||||
use hip_runtime_sys::{hipError_t, hipMemoryType, hipPointerGetAttributes};
|
use std::{ffi::c_void, ptr};
|
||||||
|
|
||||||
use crate::{
|
|
||||||
cuda::{CUdeviceptr, CUmemorytype, CUpointer_attribute},
|
|
||||||
hip_call,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(crate) unsafe fn get_attribute(
|
pub(crate) unsafe fn get_attribute(
|
||||||
data: *mut c_void,
|
data: *mut c_void,
|
||||||
attribute: CUpointer_attribute,
|
attribute: hipPointer_attribute,
|
||||||
ptr: CUdeviceptr,
|
ptr: hipDeviceptr_t,
|
||||||
) -> Result<(), hipError_t> {
|
) -> CUresult {
|
||||||
if data == ptr::null_mut() {
|
if data == ptr::null_mut() {
|
||||||
return Err(hipError_t::hipErrorInvalidValue);
|
return CUresult::ERROR_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
// 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)?;
|
||||||
}
|
}
|
||||||
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(())
|
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),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn memory_type(cu: hipMemoryType) -> Result<CUmemorytype, hipError_t> {
|
fn memory_type(cu: hipMemoryType) -> Result<CUmemorytype, hipErrorCode_t> {
|
||||||
match cu {
|
match cu {
|
||||||
hipMemoryType::hipMemoryTypeHost => Ok(CUmemorytype::CU_MEMORYTYPE_HOST),
|
hipMemoryType::hipMemoryTypeHost => Ok(CUmemorytype::CU_MEMORYTYPE_HOST),
|
||||||
hipMemoryType::hipMemoryTypeDevice => Ok(CUmemorytype::CU_MEMORYTYPE_DEVICE),
|
hipMemoryType::hipMemoryTypeDevice => Ok(CUmemorytype::CU_MEMORYTYPE_DEVICE),
|
||||||
hipMemoryType::hipMemoryTypeArray => Ok(CUmemorytype::CU_MEMORYTYPE_ARRAY),
|
hipMemoryType::hipMemoryTypeArray => Ok(CUmemorytype::CU_MEMORYTYPE_ARRAY),
|
||||||
hipMemoryType::hipMemoryTypeUnified => Ok(CUmemorytype::CU_MEMORYTYPE_UNIFIED),
|
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;
|
extern crate lazy_static;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate cuda_driver_sys;
|
extern crate cuda_driver_sys;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[macro_use]
|
|
||||||
extern crate paste;
|
extern crate paste;
|
||||||
extern crate ptx;
|
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
Add a link
Reference in a new issue