Quando una risorsa è una risorsa?

1

Quindi ho un motore di rendering, e ho un gestore risorse che aggiunge classi che derivano dal tipo "Risorsa". È un gestore risorse molto flessibile e generico, di cui solo uno può esistere (è una classe statica). Pertanto, una classe ShaderProgram o Camera può essere facilmente aggiunta in questo modo:

    rm::add("textShader",
        new ShaderProgram("assets/shaders/renderText.vert",
                          "assets/shaders/renderText.frag", true, true));

    rm::add("fpsCamera",
            new FPSCamera(glm::vec3(0.f, 0.f, 20.f), 45.f, 4.f / 3.f, 1.f, 1000.f));

Ora, questo può sembrare abbastanza semplice; ma una domanda teorica che mi pongo è: quando una risorsa è una risorsa? Come si fa a distinguere tra qualcosa che dovrebbe essere memorizzato (ad es. Una risorsa) o qualcosa che non dovrebbe essere memorizzato (ad esempio non risorsa)?

Ad esempio, so che userò il mio ShaderProgram e Camera così come Texture (tutto il tipo Resource ) molto. Per poter ottenere il tipo esplicito di una risorsa, faccio quanto segue:

convert(Camera*, rm::get("fpsCamera"))->func(); // call Camera's func()

Quindi, so che se ho bisogno di riutilizzare qualcosa più e più volte dovrei memorizzarlo nel gestore delle risorse.

Quando si parla di un'altra classe, tuttavia, diventa un po 'più complicato. Ho due altre classi: Renderable e Scene . Il rapporto tra i due è molto intimo in quanto una Renderable è una classe astratta per oggetti di rendering come Sprite , Model etc; e Scene è semplicemente un contenitore di un numero di Renderable s. Pertanto, in un'applicazione grafica è probabile che caricherò le scene e le scaricherò per liberare risorse quando richiesto. Ma non sono sicuro che Renderable debba derivare dal tipo Resource o se Scene debba derivare dal tipo Resource (chiamando quindi Scene una risorsa) o se entrambi dovrebbero essere semplicemente una risorsa. Se Renderable era una risorsa, significa che è possibile accedervi da chiunque così facile come:

convert(Model*, rm::get("someRandomModel"))->randomFunc();

Ora, prima di urlarmi riguardo la sicurezza del tipo nella funzione sopra, vorrei rassicurare tutti sul fatto che il compilatore verifica il tipo e vede se la funzione chiamata è stata risolta. Dopo tutto è un dynamic_cast .

Ad ogni modo, il dilemma continua così e in un primo momento posso solo affermare che Renderable potrebbe essere una risorsa solo se vogliamo riutilizzare i renderable in questione. Pertanto, se dovessi aggiungere un Model al gestore risorse, significa che è disponibile ovunque nel programma. Ma, non può essere recuperato se non si conosce l'ID di quella risorsa. Pertanto, è completamente possibile riutilizzare un oggetto Model per sostituire una mesh esistente al suo interno.

Senza essere troppo tecnico, faccio ancora una volta la semplice domanda: quando una risorsa è una risorsa e dove tracciamo la linea?

    
posta Poriferous 21.08.2015 - 11:07
fonte

1 risposta

4

Sebbene non esista una definizione "ufficiale" di "risorsa", il termine è generalmente utilizzato per tutto ciò che il programma deve acquisire esplicitamente prima dell'uso e, eventualmente, rilasciato dopo l'uso, dove l'atto di acquisizione e rilascio è costoso o abbastanza complicato da voler evitare di farlo più del necessario. In genere, questo include qualsiasi file che dobbiamo aprire (immagine, modello, mesh, audio, musica, dati, ecc.), Qualsiasi hardware di cui abbiamo bisogno (contesto audio, contesto grafico, ecc.) E qualsiasi connessione di rete di cui abbiamo bisogno.

I gestori di risorse generiche sono utili perché possono astrarre la necessità di preoccuparsi esattamente di quando acquisire e rilasciare la risorsa, invece di imporre regole semplici come "acquisirlo la prima volta che qualcuno lo richiede e rilasciarlo dopo nessun riferimento a rimane nella portata "che impedisce problemi di prestazioni come riaprire lo stesso file ogni volta che vogliamo usarlo, invece di lasciarlo aperto finché non abbiamo finito.

Data questa definizione di una "risorsa", probabilmente Renderable s non si qualifica. Molti Renderable s dovranno fare riferimento a una risorsa, ma ciò non significa che siano risorse stesse. Un Scene potrebbe richiedere molti dati per essere reso correttamente, ma non devono contenere tutti quei dati stessi. Ad esempio, può fare riferimento a risorse grafiche tramite nomi di file o tramite un oggetto personalizzato fornito dal gestore risorse. In questo modo, il Scene stesso è un oggetto relativamente leggero che non è più difficile da costruire rispetto a qualsiasi altro oggetto C ++, quindi non trarrebbe alcun beneficio dalla gestione come se fosse una risorsa pesante.

Oltre a questo argomento teorico, vedo altre due bandiere rosse con la tua proposta specifica. È possibile che tu non intendessi seriamente queste cose e queste risposte ammonteranno ai nitpicks, ma credo che valga la pena menzionarle a prescindere.

In primo luogo, l'unico vantaggio che citi per aver fatto Renderable o Scene deriva da Resource è che "è accessibile a chiunque". Questo non è un vantaggio. Anche se "le variabili globali sono malvagie" può essere eccessivamente dogmatico e semplicistico, dovresti generalmente fare uno sforzo per limitare l'accesso a una variabile a quelle parti del codice che effettivamente ne hanno bisogno. La logica di rendering Scene deve conoscere il gestore risorse? Probabilmente no. Il codice per disegnare il singolo Renderable s probabilmente lo fa, ma non il codice per attraversare i grafici delle scene.

In secondo luogo, nella maggior parte dei casi, l'intero punto di creare una classe base B per le classi X e Y è così che puoi chiamare b->foo() senza preoccuparti se b è di tipo X , Y o Potato . Se devi fare un dynamic_cast per assicurare "sicurezza del tipo", significa che probabilmente ti interessa il tipo concreto di b , il che significa che probabilmente non stai guadagnando nulla dalla classe base comune. Se il gestore risorse richiede che tu faccia dynamic_cast s per utilizzare le risorse che gestisce, considererei un difetto grave con il gestore; il codice generico in C ++ dovrebbe solitamente basarsi su modelli piuttosto che su dynamic_cast s per il suo tipo di sicurezza.

    
risposta data 21.08.2015 - 12:24
fonte

Leggi altre domande sui tag