--- ./src/include/OSL/oslexec.h.orig +++ ./src/include/OSL/oslexec.h @@ -428,7 +428,8 @@ class OSLEXECPUBLIC ShadingSystem std::string getstats (int level=1) const; void register_closure (string_view name, int id, const ClosureParam *params, - PrepareClosureFunc prepare, SetupClosureFunc setup); + PrepareClosureFunc prepare, SetupClosureFunc setup, + int alignment = 1); /// Query either by name or id an existing closure. If name is non /// NULL it will use it for the search, otherwise id would be used /// and the name will be placed in name if successful. Also return --- ./src/liboslexec/oslexec_pvt.h +++ ./src/liboslexec/oslexec_pvt.h @@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include "OSL/genclosure.h" #include "OSL/oslexec.h" #include "OSL/oslclosure.h" #include "osl_pvt.h" @@ -693,13 +694,16 @@ class ClosureRegistry { std::vector params; // the needed size for the structure int struct_size; + // the needed alignment of the structure + int alignment; // Creation callbacks PrepareClosureFunc prepare; SetupClosureFunc setup; }; void register_closure (string_view name, int id, const ClosureParam *params, - PrepareClosureFunc prepare, SetupClosureFunc setup); + PrepareClosureFunc prepare, SetupClosureFunc setup, + int alignmen = 1); const ClosureEntry *get_entry (ustring name) const; const ClosureEntry *get_entry (int id) const { @@ -855,7 +859,8 @@ class ShadingSystemImpl ustring *alloc_string_constants (size_t n) { return m_string_pool.alloc (n); } void register_closure (string_view name, int id, const ClosureParam *params, - PrepareClosureFunc prepare, SetupClosureFunc setup); + PrepareClosureFunc prepare, SetupClosureFunc setup, + int alignment = 1); bool query_closure (const char **name, int *id, const ClosureParam **params); const ClosureRegistry::ClosureEntry *find_closure(ustring name) const { @@ -1120,19 +1125,24 @@ class SimplePool { char * alloc(size_t size, size_t alignment=1) { // Alignment must be power of two DASSERT ((alignment & (alignment - 1)) == 0); - // Fail if beyond allocation limits or senseless alignment - if (size > BlockSize || (size & (alignment - 1)) != 0) + // Fail if beyond allocation limits (we make sure there's enough space + // for alignment padding here as well). + if (size + alignment - 1 > BlockSize) return NULL; - m_block_offset -= (m_block_offset & (alignment - 1)); // Fix up alignment - if (size <= m_block_offset) { + // Fix up alignment + size_t alignment_offset = alignment_offset_calc(alignment); + if (size + alignment_offset <= m_block_offset) { // Enough space in current block - m_block_offset -= size; + m_block_offset -= size + alignment_offset; } else { // Need to allocate a new block m_current_block++; m_block_offset = BlockSize - size; if (m_blocks.size() == m_current_block) m_blocks.push_back(new char[BlockSize]); + alignment_offset = alignment_offset_calc(alignment); + DASSERT (m_block_offset >= alignment_offset); + m_block_offset -= alignment_offset; } return m_blocks[m_current_block] + m_block_offset; } @@ -1140,6 +1150,10 @@ class SimplePool { void clear () { m_current_block = 0; m_block_offset = BlockSize; } private: + inline size_t alignment_offset_calc(size_t alignment) { + return (((uintptr_t)m_blocks[m_current_block] + m_block_offset) & (alignment - 1)); + } + std::vector m_blocks; size_t m_current_block; size_t m_block_offset; @@ -1320,7 +1334,9 @@ class OSLEXECPUBLIC ShadingContext { ClosureComponent * closure_component_allot(int id, size_t prim_size, int nattrs) { size_t needed = sizeof(ClosureComponent) + (prim_size >= 4 ? prim_size - 4 : 0) + sizeof(ClosureComponent::Attr) * nattrs; - ClosureComponent *comp = (ClosureComponent *) m_closure_pool.alloc(needed); + int alignment = m_shadingsys.find_closure(id)->alignment; + size_t alignment_offset = closure_alignment_offset_calc(alignment); + ClosureComponent *comp = (ClosureComponent *) (m_closure_pool.alloc(needed + alignment_offset, alignment) + alignment_offset); comp->type = ClosureColor::COMPONENT; comp->id = id; comp->size = prim_size; @@ -1335,7 +1351,9 @@ class OSLEXECPUBLIC ShadingContext { // Allocate the component and the mul back to back size_t needed = sizeof(ClosureComponent) + (prim_size >= 4 ? prim_size - 4 : 0) + sizeof(ClosureComponent::Attr) * nattrs; - ClosureComponent *comp = (ClosureComponent *) m_closure_pool.alloc(needed); + int alignment = m_shadingsys.find_closure(id)->alignment; + size_t alignment_offset = closure_alignment_offset_calc(alignment); + ClosureComponent *comp = (ClosureComponent *) (m_closure_pool.alloc(needed + alignment_offset, alignment) + alignment_offset); comp->type = ClosureColor::COMPONENT; comp->id = id; comp->size = prim_size; @@ -1486,6 +1504,14 @@ class OSLEXECPUBLIC ShadingContext { // Buffering of error messages and printfs typedef std::pair ErrorItem; mutable std::vector m_buffered_errors; + + // Calculate offset needed to align ClosureComponent's mem to a given alignment. + inline size_t closure_alignment_offset_calc(size_t alignment) { + return alignment == 1 + ? 0 + : alignment - (reckless_offsetof(ClosureComponent, mem) & (alignment - 1)); + } + }; --- ./src/liboslexec/shadingsys.cpp +++ ./src/liboslexec/shadingsys.cpp @@ -284,9 +284,10 @@ void ShadingSystem::register_closure (string_view name, int id, const ClosureParam *params, PrepareClosureFunc prepare, - SetupClosureFunc setup) + SetupClosureFunc setup, + int alignment) { - return m_impl->register_closure (name, id, params, prepare, setup); + return m_impl->register_closure (name, id, params, prepare, setup, alignment); } @@ -798,7 +799,8 @@ void ShadingSystemImpl::register_closure (string_view name, int id, const ClosureParam *params, PrepareClosureFunc prepare, - SetupClosureFunc setup) + SetupClosureFunc setup, + int alignment) { for (int i = 0; params && params[i].type != TypeDesc(); ++i) { if (params[i].key == NULL && params[i].type.size() != (size_t)params[i].field_size) { @@ -806,7 +808,7 @@ ShadingSystemImpl::register_closure (string_view name, int id, return; } } - m_closure_registry.register_closure(name, id, params, prepare, setup); + m_closure_registry.register_closure(name, id, params, prepare, setup, alignment); } @@ -2554,7 +2556,8 @@ void ClosureRegistry::register_closure (string_view name, int id, const ClosureParam *params, PrepareClosureFunc prepare, - SetupClosureFunc setup) + SetupClosureFunc setup, + int alignment) { if (m_closure_table.size() <= (size_t)id) m_closure_table.resize(id + 1); @@ -2578,6 +2581,7 @@ ClosureRegistry::register_closure (string_view name, int id, } entry.prepare = prepare; entry.setup = setup; + entry.alignment = alignment; m_closure_name_to_id[ustring(name)] = id; }