Panda3D
Loading...
Searching...
No Matches
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 */
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::const_iterator ci;
81 ci = _contexts->find(prepared_objects);
82 if (ci != _contexts->end()) {
83 return (*ci).second;
84 }
85 } else {
86 _contexts = new Contexts;
87 }
88
89 BufferContext *vbc = prepared_objects->prepare_shader_buffer_now(this, gsg);
90 if (vbc != nullptr) {
91 (*_contexts)[prepared_objects] = vbc;
92 }
93 else if (_contexts->empty()) {
94 delete _contexts;
95 _contexts = nullptr;
96 }
97 return vbc;
98}
99
100/**
101 * Frees the data context only on the indicated object, if it exists there.
102 * Returns true if it was released, false if it had not been prepared.
103 */
105release(PreparedGraphicsObjects *prepared_objects) {
106 if (_contexts != nullptr) {
107 Contexts::iterator ci;
108 ci = _contexts->find(prepared_objects);
109 if (ci != _contexts->end()) {
110 BufferContext *vbc = (*ci).second;
111 prepared_objects->release_shader_buffer(vbc);
112 return true;
113 }
114 }
115
116 // Maybe it wasn't prepared yet, but it's about to be.
117 return prepared_objects->dequeue_shader_buffer(this);
118}
119
120/**
121 * Frees the context allocated on all objects for which the data has been
122 * declared. Returns the number of contexts which have been freed.
123 */
125release_all() {
126 int num_freed = 0;
127
128 if (_contexts != nullptr) {
129 // We have to traverse a copy of the _contexts list, because the
130 // PreparedGraphicsObjects object will call clear_prepared() in response
131 // to each release_shader_buffer(), and we don't want to be modifying the
132 // _contexts list while we're traversing it.
133 Contexts temp = *_contexts;
134 num_freed = (int)_contexts->size();
135
136 Contexts::const_iterator ci;
137 for (ci = temp.begin(); ci != temp.end(); ++ci) {
138 PreparedGraphicsObjects *prepared_objects = (*ci).first;
139 BufferContext *vbc = (*ci).second;
140 prepared_objects->release_shader_buffer(vbc);
141 }
142
143 // Now that we've called release_shader_buffer() on every known context,
144 // the _contexts list should have completely emptied itself.
145 nassertr(_contexts == nullptr, num_freed);
146 }
147
148 return num_freed;
149}
150
151/**
152 * Removes the indicated PreparedGraphicsObjects table from the buffer's
153 * table, without actually releasing the texture. This is intended to be
154 * called only from PreparedGraphicsObjects::release_shader_buffer(); it
155 * should never be called by user code.
156 */
157void ShaderBuffer::
158clear_prepared(PreparedGraphicsObjects *prepared_objects) {
159 nassertv(_contexts != nullptr);
160
161 Contexts::iterator ci;
162 ci = _contexts->find(prepared_objects);
163 if (ci != _contexts->end()) {
164 _contexts->erase(ci);
165 if (_contexts->empty()) {
166 delete _contexts;
167 _contexts = nullptr;
168 }
169 } else {
170 // If this assertion fails, clear_prepared() was given a prepared_objects
171 // which the data array didn't know about.
172 nassert_raise("unknown PreparedGraphicsObjects");
173 }
174}
175
176/**
177 * Tells the BamReader how to create objects of type ParamValue.
178 */
181 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
182}
183
184/**
185 * Writes the contents of this object to the datagram for shipping out to a
186 * Bam file.
187 */
189write_datagram(BamWriter *manager, Datagram &dg) {
190 dg.add_string(get_name());
191 dg.add_uint64(_data_size_bytes);
192 dg.add_uint8(_usage_hint);
193 dg.add_bool(!_initial_data.empty());
194 dg.append_data(_initial_data.data(), _initial_data.size());
195}
196
197/**
198 * This function is called by the BamReader's factory when a new object of
199 * type ParamValue is encountered in the Bam file. It should create the
200 * ParamValue and extract its information from the file.
201 */
202TypedWritable *ShaderBuffer::
203make_from_bam(const FactoryParams &params) {
204 ShaderBuffer *param = new ShaderBuffer;
205 DatagramIterator scan;
206 BamReader *manager;
207
208 parse_params(params, scan, manager);
209 param->fillin(scan, manager);
210
211 return param;
212}
213
214/**
215 * This internal function is called by make_from_bam to read in all of the
216 * relevant data from the BamFile for the new ParamValue.
217 */
218void ShaderBuffer::
219fillin(DatagramIterator &scan, BamReader *manager) {
220 set_name(scan.get_string());
221 _data_size_bytes = scan.get_uint64();
222 _usage_hint = (UsageHint)scan.get_uint8();
223
224 if (scan.get_bool() && _data_size_bytes > 0) {
225 nassertv_always(_data_size_bytes <= scan.get_remaining_size());
226 _initial_data.resize((_data_size_bytes + 15u) & ~15u);
227 scan.extract_bytes(&_initial_data[0], _data_size_bytes);
228 } else {
229 _initial_data.clear();
230 }
231}
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...
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...
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.
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.
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.