Git Product home page Git Product logo

citro3d-rs's People

Contributors

0x00002a avatar centdemeern1 avatar ian-h-chamberlain avatar meziu avatar panicbit avatar tamara-schmitz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

citro3d-rs's Issues

Safety problems and links with ctru-rs

Citro3D is designed to be mostly used alone (an exception is the use of Citro2D, which is based on the aforementioned). This is a problem because the original implementation makes many assumptions which we cannot prove in a normal environment, but that we need to to ensure memory safety and correct execution.

For example, we cannot have the use of RawFramebuffers without taking the gfx::Screen‘s write lock. Simply passing immutable references and such is not safe, as the underlying C implementation could change the environment regardless.

We need to thoroughly examine Citro3D’s code and check for all of the functions that mutate the environment (like changing the framebuffer’s format, or even just displaying to the screen) and make appropriate changes to ensure a safe library.

Example for things to avoid:
https://github.com/ian-h-chamberlain/citro3d-rs/blob/6ba85149d84aa3bcc879ec16ef79079dc411643f/citro3d/src/render.rs#L61

Because the choice of Screen target is permanent, but only a simple immutable reference is passed. Tracking internal changes would be impossible. The screen’s locked reference (RefMut) should be held by the struct.

C3D_BindProgram stores a pointer to a Program (use-after-free in bind_program)

C3D_BindProgram stores the passed-in pointer to a shader::Program in the C3D context. Currently, bind_program takes a reference to a Program, meaning that it's possible to pass in a Program that is dropped before the context attempts to use it (at the end of the frame, when it's rendered). This leads to a use-after-free and generally a crash.
This can be avoided by the Instance taking ownership of the passed-in Program, and storing it in some kind of data type that can be Pinned.

Automatically build shaders

Similar to the cc-rs crate, it would be nice to compile shaders automatically in one of these ways:

  • build script helper crate (probably looks very similar to cc-rs in practice)

    • include_bytes!(concat!(env!("OUT_DIR"), "/shader.shbin")) ? looks kinda messy but would work

    • somehow include built shader bin in romfs – maybe hard link / symlink can do this?

  • Proc macro? Basically would run the shader compiler and spit out bytes... probably would increase compile time poorly

Recommended way to store context and targets

Hi,
I'm new to rust as I'm more used to C and C++, I've been trying to work on a rust engine supporting 3ds however i'm having some issues.
Basically I want to have a struct that contains the data related to graphics of the engine. So the context etc
I originally approached it by trying to reproduce the triangle example but putting the data in a struct etc instead of putting everything in main
image

however when constructing the struct I realise that due to the self references, i can't make an appropriate constructor
so I'm wondering what's the recommended approach when working with citro3d-rs

Citro2D support for 2D applications?

Is support for Citro2D on the checklist? I would quite like to use Rust3DS for my homebrew applications, but it doesn't appear to support C2D unfortunately :/

Missing Bindings: citro3d/tex3ds.h

Without these bindings, It is currently impossible to use textures within a rust environment

EDIT: this may technically come under another repo, But its a essential feature

Missing Bindings: c3d/texture.h

After looking for a reference to C3D_TexSetFilter inside of the bindings, I've come to find out that C3D_TexSetFilter is an inlined function inside of c3d/texture.h which has been missed.

Do keep in mind the missing binding is a static inline, So its missing

API of Instance is fundamentally unsound

Hi. I'm @Jhynjhiruu's friend. Just wanna preface this by saying this library has been incredibly useful as a reference when working out citro3d, I really appreciate the effort that's gone into this. Now onto the problems

The interface exposed by Instance is fundamentally unsound, what do I mean by this? Well it makes guarantees to/as safe code that it doesn't uphold. Some examples:

  • #35
  • #37
  • #36
  • draw_arrays doesn't require the underlying 'vbo to outlive the frame end (which will cause use-after-free)

The main cause of use-after-free's is the lack of lifetimes for things which need to stick around until the frame ends (when they will be read by the GPU). In its current form at the very least draw_arrays and bind_program need to be marked unsafe (bind_program especially is really nasty because of its pinning requirements).

Alternatively, the lifetimes can be made to work. It just requires moving the frame stuff to a RAII wrapper rather than exclusively render_frame_with. I've created a prototype/proof of concept here I'm not married to it but it fixes everything but #35 which I left alone because of #38. It also lays the foundation for implementing stuff like textures in a safe way as well (as the lifetimes are now there to enforce it).

Texenvs need to stay alive until they're drawn

Yeah, I saw that a little while ago. Unfortunately, the main bit of rendering a model it doesn't touch, textures, is the bit I'm having difficulty with. I've successfully got a shape with a texture, but I find myself hopelessly lost trying to understand how the texture pipeline is supposed to work and I had to go a fair bit against my understanding of how it should work in order to get two faces with two different textures.
Please enjoy this square, which took me about 9 hours to get textured:

PXL_20231223_094143210.mp4

(Sorry for the terrible recording quality. I should have turned down my screen brightness first.)
The problem I'm having is that the texture pipeline seems to persist state across draw calls (Instance::draw_arrays calls, really), even when I think it shouldn't be - first, enabling textures for only the first face and resetting the TexEnv pipeline for the second did nothing, giving me a lovely yellow square (texture coordinates (0.0, 0.0) on Bowser's face) on the back; and second, using two separate textures for the two sides gave me Peach on both sides, for some reason (the Peach texture got used for both sides instead of only the second side, as if the GPU were batching the draws and preserving only the last-written texture). I worked around the issue by merging the textures into one, using it for both draw calls, and adjusting the texture coordinates to match.
I suppose I can technically deal with this by merging all the textures for everything that's supposed to be drawn on one frame into one giant texture and using that for every shape that frame, but it feels like I'm misunderstanding something fundamental about how textures are supposed to work. Either that or it's a bug.
(By the way, having a safe wrapper for draw_elements would be pretty handy in the future for optimising the number of vertices.)


My friend figured it out, and in retrospect it's sort of obvious - textures have to be alive until they're drawn, and if they're freed before the end of the frame, strange things happen. TexEnvs still don't work how I think they do, but at least I can draw more than one texture at a time now.

Originally posted by @Jhynjhiruu in #35 (comment)

More docs improvements

Couple things that could fall under this, but mainly

  • html_root_url and favicons like in rust3ds/ctru-rs#147
  • More doc examples... they're rather sparse here
  • Update READMEs to be more than stubs and maybe link back to ctru-rs docs in some places
  • Anything else?

Dropping Instance in the wrong order causes a crash on exit

Hi there,
I've had a strange crash in my project for the past while, in which the program crashes while dropping the Targets for the top screen. I wasn't able to figure out exactly what's going wrong, until I noticed the difference between my program and the example triangle.rs - my code was creating the Instance object after the Targets, and triangle.rs was creating it before. Given what I know about a Target being bound to an Instance, this makes a weird kind of sense - initialising the Target before the Instance means that Rust will drop the Instance first, and the instance calls C3D_Fini when it's dropped, which presumably does something weird. (The crash itself is in the call to free within the C code, so presumably this also manifests using the C toolchain, though I didn't test that.)
I was able to fix the crash pretty simply, by changing the Instance to be initialised first. Is there a better fix? Either unlinking the bound Target on drop somehow, or something fancy with lifetimes to ensure that the Instance must outlive the Target attached to it?
(For a simple repro of the crash, move line 61 of triangle.rs to line 83 (other places may also work), then build and run it on a real 3DS. Citra doesn't care about the crash, since it's on exit, but on a real 3DS, it means exiting to the Homebrew Menu or the HOME Menu isn't possible, which sucks a lot for testing.)

Example Porting issue: Normal Mapping

I'm having trouble porting the Normal Mapping example from C to Rust to test the new bindings. The only difference is in image and shader loading and I can't really put my finger on whats wrong. For some reason the 3ds freezes at C3D_FrameBegin

https://gist.github.com/hYdos/c260e0afe72200a4872e7f9000ddae5d - main.rs
https://gist.github.com/hYdos/8f4c4bea934714be008d7157b1512c79 - util.rs

Wondering if you guys would have more knowledge to whats going on

Assets should not be the issue as i use the command from the bitmap example in rust3ds/citru-rs to generate textures and use picasso to generate the shader bytes

Triangle example runs on citra but gets black screen on hardware

Not much to describe. triangle.rs from the examples folder runs and displays a triangle on citra but when testing on my n3ds(xl) its a black screen. I'm assuming its waiting/hanging on something as the home menu button is unresponsive. Rosalina is still usable while its like this.

Deadlock in render::Target::drop

Reproducing code is https://github.com/CenTdemeern1/witness-rs/tree/main/frontend-3ds

Deadlock stack trace seems to be this:

#0  svcArbitrateAddressNoTimeout () at /Users/davem/projects/devkitpro/pacman-packages/libctru/src/libctru-2.3.1/libctru/source/svc.s:253
#1  0x00107bd8 in syncArbitrateAddress (addr=<optimized out>, type=<optimized out>, value=<optimized out>) at /Users/davem/projects/devkitpro/pacman-packages/libctru/src/libctru-2.3.1/libctru/source/synchronization.c:22
#2  0x0010683c in gspWaitForAnyEvent () at /Users/davem/projects/devkitpro/pacman-packages/libctru/src/libctru-2.3.1/libctru/source/services/gspgpu.c:311
#3  0x00136d3c in gxCmdQueueWait (queue=<optimized out>, timeout=<optimized out>) at /Users/davem/projects/devkitpro/pacman-packages/libctru/src/libctru-2.3.1/libctru/source/gpu/gxqueue.c:116
#4  0x00133be0 in C3Di_WaitAndClearQueue (timeout=<optimized out>) at /Users/davem/projects/devkitpro/pacman-packages/citro3d/src/citro3d-1.7.1/source/renderqueue.c:95
#5  0x001342f4 in C3D_RenderTargetSetOutput (target=target@entry=0x0, screen=GFX_TOP, side=GFX_LEFT, transferFlags=transferFlags@entry=0) at /Users/davem/projects/devkitpro/pacman-packages/citro3d/src/citro3d-1.7.1/source/renderqueue.c:381
#6  0x00134318 in C3D_RenderTargetDetachOutput (target=target@entry=0x82048a8) at /Users/davem/projects/devkitpro/pacman-packages/citro3d/src/citro3d-1.7.1/include/c3d/renderqueue.h:69
#7  0x00134348 in C3D_RenderTargetDelete (target=0x82048a8) at /Users/davem/projects/devkitpro/pacman-packages/citro3d/src/citro3d-1.7.1/source/renderqueue.c:366
#8  0x00112bd0 in citro3d::render::{impl#0}::drop (self=0x81ffb6c) at src/render.rs:33
#9  0x001010d8 in core::ptr::drop_in_place<citro3d::render::Target> () at /Users/ianchamberlain/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:514
#10 0x001034e4 in witness_3ds::main () at frontend-3ds/src/main.rs:105

Originally posted by @CenTdemeern1 in rust3ds/ctru-rs#179

Example that renders a more complex model

Hi, a couple years ago I was tinkering with citro3d-rs and got to the point of being able to load a model from an .obj file (using obj-rs) and display it with stereoscopic 3d.

I think it'd be pretty nice to have as an example, and I could potentially spend some time reimplementing it on modern citro3d-rs if you're interested. I'm not sure if having a example that uses obj-rs would be too heavyweight though. I also had a variant that just renders a cube at one point.

I also pushed my code to https://github.com/vivlim/citro3d-rs-2021 in case it'd be useful, the readme also links to a video of it running on hardware. The code is a mess in part because I was learning as I went, and then burned out.

Merge with vs replace upstream repo?

I started this as a fork, but perhaps once it reaches a certain point it can just be moved into the upstream as rust3ds/citro3d-rs and the https://github.com/rust3ds/citro3d-sys repo can be archived or something like that.

It might make sense to wait for a reasonable level of quality and/or other rust3ds org changes before doing this.

Safe wrapper for buffer info

#4 (comment)

Basically, we should be able to create a BufInfo object that borrows the backing VBO, so we don't have to pass raw pointers and we can guarantee the data lives as long as needed for it to be rendered.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.