Panda3D
shaderBuffer.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file shaderBuffer.cxx
10 * @author rdb
11 * @date 2016-12-12
12 */
13
14#include "shaderBuffer.h"
16
17TypeHandle ShaderBuffer::_type_handle;
18
19/**
20 * Destructor.
21 */
25}
26
27/**
28 *
29 */
30void ShaderBuffer::
31output(std::ostream &out) const {
32 out << "buffer " << get_name() << ", " << _data_size_bytes << "B, " << _usage_hint;
33}
34
35/**
36 * Indicates that the data should be enqueued to be prepared in the indicated
37 * prepared_objects at the beginning of the next frame. This will ensure the
38 * data is already loaded into the GSG if it is expected to be rendered soon.
39 *
40 * Use this function instead of prepare_now() to preload datas from a user
41 * interface standpoint.
42 */
44prepare(PreparedGraphicsObjects *prepared_objects) {
45 prepared_objects->enqueue_shader_buffer(this);
46}
47
48/**
49 * Returns true if the data has already been prepared or enqueued for
50 * preparation on the indicated GSG, false otherwise.
51 */
53is_prepared(PreparedGraphicsObjects *prepared_objects) const {
54 if (_contexts == nullptr) {
55 return false;
56 }
57 Contexts::const_iterator ci;
58 ci = _contexts->find(prepared_objects);
59 if (ci != _contexts->end()) {
60 return true;
61 }
62 return prepared_objects->is_shader_buffer_queued(this);
63}
64
65/**
66 * Creates a context for the data on the particular GSG, if it does not
67 * already exist. Returns the new (or old) BufferContext. This assumes
68 * that the GraphicsStateGuardian is the currently active rendering context
69 * and that it is ready to accept new datas. If this is not necessarily the
70 * case, you should use prepare() instead.
71 *
72 * Normally, this is not called directly except by the GraphicsStateGuardian;
73 * a data does not need to be explicitly prepared by the user before it may be
74 * rendered.
75 */
77prepare_now(PreparedGraphicsObjects *prepared_objects,
79 if (_contexts == nullptr) {
80 _contexts = new Contexts;
81 }
82 Contexts::const_iterator ci;
83 ci = _contexts->find(prepared_objects);
84 if (ci != _contexts->end()) {
85 return (*ci).second;
86 }
87
88 BufferContext *vbc = prepared_objects->prepare_shader_buffer_now(this, gsg);
89 if (vbc != nullptr) {
90 (*_contexts)[prepared_objects] = vbc;
91 }
92 return vbc;
93}
94
95/**
96 * Frees the data context only on the indicated object, if it exists there.
97 * Returns true if it was released, false if it had not been prepared.
98 */
100release(PreparedGraphicsObjects *prepared_objects) {
101 if (_contexts != nullptr) {
102 Contexts::iterator ci;
103 ci = _contexts->find(prepared_objects);
104 if (ci != _contexts->end()) {
105 BufferContext *vbc = (*ci).second;
106 prepared_objects->release_shader_buffer(vbc);
107 return true;
108 }
109 }
110
111 // Maybe it wasn't prepared yet, but it's about to be.
112 return prepared_objects->dequeue_shader_buffer(this);
113}
114
115/**
116 * Frees the context allocated on all objects for which the data has been
117 * declared. Returns the number of contexts which have been freed.
118 */
120release_all() {
121 int num_freed = 0;
122
123 if (_contexts != nullptr) {
124 // We have to traverse a copy of the _contexts list, because the
125 // PreparedGraphicsObjects object will call clear_prepared() in response
126 // to each release_shader_buffer(), and we don't want to be modifying the
127 // _contexts list while we're traversing it.
128 Contexts temp = *_contexts;
129 num_freed = (int)_contexts->size();
130
131 Contexts::const_iterator ci;
132 for (ci = temp.begin(); ci != temp.end(); ++ci) {
133 PreparedGraphicsObjects *prepared_objects = (*ci).first;
134 BufferContext *vbc = (*ci).second;
135 prepared_objects->release_shader_buffer(vbc);
136 }
137
138 // Now that we've called release_shader_buffer() on every known context,
139 // the _contexts list should have completely emptied itself.
140 nassertr(_contexts == nullptr, num_freed);
141 }
142
143 return num_freed;
144}
145
146/**
147 * Removes the indicated PreparedGraphicsObjects table from the buffer's
148 * table, without actually releasing the texture. This is intended to be
149 * called only from PreparedGraphicsObjects::release_shader_buffer(); it
150 * should never be called by user code.
151 */
152void ShaderBuffer::
153clear_prepared(PreparedGraphicsObjects *prepared_objects) {
154 nassertv(_contexts != nullptr);
155
156 Contexts::iterator ci;
157 ci = _contexts->find(prepared_objects);
158 if (ci != _contexts->end()) {
159 _contexts->erase(ci);
160 if (_contexts->empty()) {
161 delete _contexts;
162 _contexts = nullptr;
163 }
164 } else {
165 // If this assertion fails, clear_prepared() was given a prepared_objects
166 // which the data array didn't know about.
167 nassert_raise("unknown PreparedGraphicsObjects");
168 }
169}
170
171/**
172 * Tells the BamReader how to create objects of type ParamValue.
173 */
176 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
177}
178
179/**
180 * Writes the contents of this object to the datagram for shipping out to a
181 * Bam file.
182 */
184write_datagram(BamWriter *manager, Datagram &dg) {
185 dg.add_string(get_name());
186 dg.add_uint64(_data_size_bytes);
187 dg.add_uint8(_usage_hint);
188 dg.add_bool(!_initial_data.empty());
189 dg.append_data(_initial_data.data(), _initial_data.size());
190}
191
192/**
193 * This function is called by the BamReader's factory when a new object of
194 * type ParamValue is encountered in the Bam file. It should create the
195 * ParamValue and extract its information from the file.
196 */
197TypedWritable *ShaderBuffer::
198make_from_bam(const FactoryParams &params) {
199 ShaderBuffer *param = new ShaderBuffer;
200 DatagramIterator scan;
201 BamReader *manager;
202
203 parse_params(params, scan, manager);
204 param->fillin(scan, manager);
205
206 return param;
207}
208
209/**
210 * This internal function is called by make_from_bam to read in all of the
211 * relevant data from the BamFile for the new ParamValue.
212 */
213void ShaderBuffer::
214fillin(DatagramIterator &scan, BamReader *manager) {
215 set_name(scan.get_string());
216 _data_size_bytes = scan.get_uint64();
217 _usage_hint = (UsageHint)scan.get_uint8();
218
219 if (scan.get_bool() && _data_size_bytes > 0) {
220 nassertv_always(_data_size_bytes <= scan.get_remaining_size());
221 _initial_data.resize((_data_size_bytes + 15u) & ~15u);
222 scan.extract_bytes(&_initial_data[0], _data_size_bytes);
223 } else {
224 _initial_data.clear();
225 }
226}
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition: bamReader.I:275
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
This is a base class for those kinds of SavedContexts that occupy an easily-measured (and substantial...
Definition: bufferContext.h:38
A class to retrieve the individual data elements previously stored in a Datagram.
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
uint64_t get_uint64()
Extracts an unsigned 64-bit integer.
vector_uchar extract_bytes(size_t size)
Extracts the indicated number of bytes in the datagram and returns them as a string.
bool get_bool()
Extracts a boolean value.
std::string get_string()
Extracts a variable-length string.
size_t get_remaining_size() const
Return the bytes left in the datagram.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
Definition: datagram.I:50
void add_bool(bool value)
Adds a boolean value to the datagram.
Definition: datagram.I:34
void append_data(const void *data, size_t size)
Appends some more raw data to the end of the datagram.
Definition: datagram.cxx:129
void add_uint64(uint64_t value)
Adds an unsigned 64-bit integer to the datagram.
Definition: datagram.I:103
void add_string(const std::string &str)
Adds a variable-length string to the datagram.
Definition: datagram.I:219
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:73
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
A table of objects that are saved within the graphics context for reference by handle later.
bool is_shader_buffer_queued(const ShaderBuffer *data) const
Returns true if the index buffer has been queued on this GSG, false otherwise.
void release_shader_buffer(BufferContext *bc)
Indicates that a data context, created by a previous call to prepare_shader_buffer(),...
bool dequeue_shader_buffer(ShaderBuffer *data)
Removes a buffer from the queued list of data arrays to be prepared.
BufferContext * prepare_shader_buffer_now(ShaderBuffer *data, GraphicsStateGuardianBase *gsg)
Immediately creates a new BufferContext for the indicated data and returns it.
void enqueue_shader_buffer(ShaderBuffer *data)
Indicates that a buffer would like to be put on the list to be prepared when the GSG is next ready to...
This is a generic buffer object that lives in graphics memory.
Definition: shaderBuffer.h:33
bool is_prepared(PreparedGraphicsObjects *prepared_objects) const
Returns true if the data has already been prepared or enqueued for preparation on the indicated GSG,...
bool release(PreparedGraphicsObjects *prepared_objects)
Frees the data context only on the indicated object, if it exists there.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
BufferContext * prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the data on the particular GSG, if it does not already exist.
static void register_with_read_factory()
Tells the BamReader how to create objects of type ParamValue.
void prepare(PreparedGraphicsObjects *prepared_objects)
Indicates that the data should be enqueued to be prepared in the indicated prepared_objects at the be...
~ShaderBuffer()
Destructor.
int release_all()
Frees the context allocated on all objects for which the data has been declared.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.