mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-22 09:01:57 -05:00
Dreamcast: Cope better with running out of memory for vertex buffer
This commit is contained in:
parent
5f5d8824fa
commit
459390ef7b
2 changed files with 25 additions and 54 deletions
|
@ -507,10 +507,27 @@ cc_bool Gfx_WarnIfNecessary(void) {
|
|||
*----------------------------------------------------------Drawing--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
extern void apply_poly_header(pvr_poly_hdr_t* header, int list_type);
|
||||
static cc_bool loggedNoVRAM;
|
||||
|
||||
extern Vertex* DrawColouredQuads(const void* src, Vertex* dst, int numQuads);
|
||||
extern Vertex* DrawTexturedQuads(const void* src, Vertex* dst, int numQuads);
|
||||
|
||||
static Vertex* ReserveOutput(AlignedVector* vec, uint32_t elems) {
|
||||
Vertex* beg;
|
||||
for (;;)
|
||||
{
|
||||
if ((beg = aligned_vector_reserve(vec, elems))) return beg;
|
||||
// Try to reduce view distance to save on RAM
|
||||
if (Game_ReduceVRAM()) continue;
|
||||
|
||||
if (!loggedNoVRAM) {
|
||||
loggedNoVRAM = true;
|
||||
Logger_SysWarn(ERR_OUT_OF_MEMORY, "allocating temp memory");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawQuads(int count, void* src) {
|
||||
if (!count) return;
|
||||
PolyList* output = _glActivePolyList();
|
||||
|
@ -518,7 +535,8 @@ void DrawQuads(int count, void* src) {
|
|||
|
||||
uint32_t header_required = (vec->size == 0) || STATE_DIRTY;
|
||||
// Reserve room for the vertices and header
|
||||
Vertex* beg = aligned_vector_reserve(&output->vector, vec->size + (header_required) + count);
|
||||
Vertex* beg = ReserveOutput(&output->vector, vec->size + (header_required) + count);
|
||||
if (!beg) return;
|
||||
|
||||
if (header_required) {
|
||||
apply_poly_header((pvr_poly_hdr_t*)beg, output->list_type);
|
||||
|
|
59
third_party/gldc/src/aligned_vector.h
vendored
59
third_party/gldc/src/aligned_vector.h
vendored
|
@ -30,12 +30,6 @@ typedef struct {
|
|||
#define ROUND_TO_CHUNK_SIZE(v) \
|
||||
((((v) + ALIGNED_VECTOR_CHUNK_SIZE - 1) / ALIGNED_VECTOR_CHUNK_SIZE) * ALIGNED_VECTOR_CHUNK_SIZE)
|
||||
|
||||
|
||||
AV_FORCE_INLINE void* aligned_vector_at(const AlignedVector* vector, const uint32_t index) {
|
||||
assert(index < vector->size);
|
||||
return vector->data + (index * AV_ELEMENT_SIZE);
|
||||
}
|
||||
|
||||
AV_FORCE_INLINE void* aligned_vector_reserve(AlignedVector* vector, uint32_t element_count) {
|
||||
uint32_t original_byte_size = (vector->size * AV_ELEMENT_SIZE);
|
||||
|
||||
|
@ -49,66 +43,25 @@ AV_FORCE_INLINE void* aligned_vector_reserve(AlignedVector* vector, uint32_t ele
|
|||
uint32_t new_byte_size = (element_count * AV_ELEMENT_SIZE);
|
||||
uint8_t* original_data = vector->data;
|
||||
|
||||
vector->data = (uint8_t*) memalign(0x20, new_byte_size);
|
||||
assert(vector->data);
|
||||
uint8_t* data = (uint8_t*) memalign(0x20, new_byte_size);
|
||||
if (!data) return NULL;
|
||||
|
||||
memcpy(vector->data, original_data, original_byte_size);
|
||||
memcpy(data, original_data, original_byte_size);
|
||||
free(original_data);
|
||||
|
||||
vector->data = data;
|
||||
vector->capacity = element_count;
|
||||
return vector->data + original_byte_size;
|
||||
}
|
||||
|
||||
/* Resizes the array and returns a pointer to the first new element (if upsizing) or NULL (if downsizing) */
|
||||
AV_FORCE_INLINE void* aligned_vector_resize(AlignedVector* vector, const uint32_t element_count) {
|
||||
void* ret = NULL;
|
||||
|
||||
uint32_t previous_count = vector->size;
|
||||
if(vector->capacity <= element_count) {
|
||||
/* If we didn't have capacity, increase capacity (slow) */
|
||||
|
||||
aligned_vector_reserve(vector, element_count);
|
||||
vector->size = element_count;
|
||||
|
||||
ret = aligned_vector_at(vector, previous_count);
|
||||
|
||||
av_assert(vector->size == element_count);
|
||||
av_assert(vector->size <= vector->capacity);
|
||||
} else if(previous_count < element_count) {
|
||||
/* So we grew, but had the capacity, just get a pointer to
|
||||
* where we were */
|
||||
vector->size = element_count;
|
||||
av_assert(vector->size < vector->capacity);
|
||||
ret = aligned_vector_at(vector, previous_count);
|
||||
} else if(vector->size != element_count) {
|
||||
vector->size = element_count;
|
||||
av_assert(vector->size < vector->capacity);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AV_FORCE_INLINE void* aligned_vector_push_back(AlignedVector* vector, const void* objs, uint32_t count) {
|
||||
/* Resize enough room */
|
||||
assert(count);
|
||||
#ifndef NDEBUG
|
||||
uint32_t initial_size = vector->size;
|
||||
#endif
|
||||
|
||||
uint8_t* dest = (uint8_t*) aligned_vector_resize(vector, vector->size + count);
|
||||
uint8_t* dest = (uint8_t*) aligned_vector_reserve(vector, vector->size + count);
|
||||
assert(dest);
|
||||
|
||||
/* Copy the objects in */
|
||||
memcpy(dest, objs, count * AV_ELEMENT_SIZE);
|
||||
|
||||
assert(vector->size == initial_size + count);
|
||||
vector->size += count;
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
AV_FORCE_INLINE void* aligned_vector_extend(AlignedVector* vector, const uint32_t additional_count) {
|
||||
void* ret = aligned_vector_resize(vector, vector->size + additional_count);
|
||||
assert(ret); // Should always return something
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue