Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions core/templates/hash_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class HashMap : private Allocator {
static constexpr uint32_t MIN_CAPACITY_INDEX = 2; // Use a prime.
static constexpr float MAX_OCCUPANCY = 0.75;
static constexpr uint32_t EMPTY_HASH = 0;
using KV = KeyValue<TKey, TValue>; // Type alias for easier access to KeyValue.

private:
HashMapElement<TKey, TValue> **_elements = nullptr;
Expand Down Expand Up @@ -590,6 +591,22 @@ class HashMap : private Allocator {
}
}

HashMap(HashMap &&p_other) {
_elements = p_other._elements;
_hashes = p_other._hashes;
_head_element = p_other._head_element;
_tail_element = p_other._tail_element;
_capacity_idx = p_other._capacity_idx;
_size = p_other._size;

p_other._elements = nullptr;
p_other._hashes = nullptr;
p_other._head_element = nullptr;
p_other._tail_element = nullptr;
p_other._capacity_idx = MIN_CAPACITY_INDEX;
p_other._size = 0;
}

void operator=(const HashMap &p_other) {
if (this == &p_other) {
return; // Ignore self assignment.
Expand All @@ -609,6 +626,36 @@ class HashMap : private Allocator {
}
}

HashMap &operator=(HashMap &&p_other) {
if (this == &p_other) {
return *this;
}

if (_size != 0) {
clear();
}
if (_elements != nullptr) {
Memory::free_static(_elements);
Memory::free_static(_hashes);
}

_elements = p_other._elements;
_hashes = p_other._hashes;
_head_element = p_other._head_element;
_tail_element = p_other._tail_element;
_capacity_idx = p_other._capacity_idx;
_size = p_other._size;

p_other._elements = nullptr;
p_other._hashes = nullptr;
p_other._head_element = nullptr;
p_other._tail_element = nullptr;
p_other._capacity_idx = MIN_CAPACITY_INDEX;
p_other._size = 0;

return *this;
}

HashMap(uint32_t p_initial_capacity) {
// Capacity can't be 0.
_capacity_idx = 0;
Expand Down
4 changes: 4 additions & 0 deletions doc/classes/RDVertexAttribute.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
<tutorials>
</tutorials>
<members>
<member name="binding" type="int" setter="set_binding" getter="get_binding" default="4294967295">
The index of the buffer in the vertex buffer array to bind this vertex attribute. When set to [code]-1[/code], it defaults to the index of the attribute.
[b]Note:[/b] You cannot mix binding explicitly assigned attributes with implicitly assigned ones (i.e. [code]-1[/code]). Either all attributes must have their binding set to [code]-1[/code], or all must have explicit bindings.
</member>
<member name="format" type="int" setter="set_format" getter="get_format" enum="RenderingDevice.DataFormat" default="232">
The way that this attribute's data is interpreted when sent to a shader.
</member>
Expand Down
11 changes: 11 additions & 0 deletions doc/classes/RenderingDevice.xml
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,17 @@
Binds [param vertex_array] to the specified [param draw_list].
</description>
</method>
<method name="draw_list_bind_vertex_buffers_format">
<return type="void" />
<param index="0" name="draw_list" type="int" />
<param index="1" name="vertex_format" type="int" />
<param index="2" name="vertex_count" type="int" />
<param index="3" name="vertex_buffers" type="RID[]" />
<param index="4" name="offsets" type="PackedInt64Array" default="PackedInt64Array()" />
<description>
Binds a set of [param vertex_buffers] directly to the specified [param draw_list] using [param vertex_format] without creating a vertex array RID. Provide the number of vertices in [param vertex_count]; optional per-buffer byte [param offsets] may also be supplied.
</description>
</method>
<method name="draw_list_disable_scissor">
<return type="void" />
<param index="0" name="draw_list" type="int" />
Expand Down
68 changes: 51 additions & 17 deletions drivers/d3d12/rendering_device_driver_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1165,6 +1165,24 @@ uint8_t *RenderingDeviceDriverD3D12::buffer_persistent_map_advance(BufferID p_bu
return buf_info->persistent_ptr + buf_info->frame_idx * buf_info->size;
}

uint64_t RenderingDeviceDriverD3D12::buffer_get_dynamic_offsets(Span<BufferID> p_buffers) {
uint64_t mask = 0u;
uint64_t shift = 0u;

for (const BufferID &buf : p_buffers) {
const BufferInfo *buf_info = (const BufferInfo *)buf.id;
if (!buf_info->is_dynamic()) {
continue;
}
const BufferDynamicInfo *dyn_buf = (const BufferDynamicInfo *)buf.id;
mask |= dyn_buf->frame_idx << shift;
// We can encode the frame index in 2 bits since frame_count won't be > 4.
shift += 2UL;
}

return mask;
}

uint64_t RenderingDeviceDriverD3D12::buffer_get_device_address(BufferID p_buffer) {
const BufferInfo *buf_info = (const BufferInfo *)p_buffer.id;
return buf_info->resource->GetGPUVirtualAddress();
Expand Down Expand Up @@ -2183,27 +2201,36 @@ bool RenderingDeviceDriverD3D12::sampler_is_format_supported_for_filter(DataForm
/**** VERTEX ARRAY ****/
/**********************/

RDD::VertexFormatID RenderingDeviceDriverD3D12::vertex_format_create(VectorView<VertexAttribute> p_vertex_attribs) {
RDD::VertexFormatID RenderingDeviceDriverD3D12::vertex_format_create(Span<VertexAttribute> p_vertex_attribs, const VertexAttributeBindingsMap &p_vertex_bindings) {
VertexFormatInfo *vf_info = VersatileResource::allocate<VertexFormatInfo>(resources_allocator);

vf_info->input_elem_descs.resize(p_vertex_attribs.size());
vf_info->vertex_buffer_strides.resize(p_vertex_attribs.size());

uint32_t max_binding = 0;
for (uint32_t i = 0; i < p_vertex_attribs.size(); i++) {
vf_info->input_elem_descs[i] = {};
vf_info->input_elem_descs[i].SemanticName = "TEXCOORD";
vf_info->input_elem_descs[i].SemanticIndex = p_vertex_attribs[i].location;
vf_info->input_elem_descs[i].Format = RD_TO_D3D12_FORMAT[p_vertex_attribs[i].format].general_format;
vf_info->input_elem_descs[i].InputSlot = i; // TODO: Can the same slot be used if data comes from the same buffer (regardless format)?
vf_info->input_elem_descs[i].AlignedByteOffset = p_vertex_attribs[i].offset;
if (p_vertex_attribs[i].frequency == VERTEX_FREQUENCY_INSTANCE) {
vf_info->input_elem_descs[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
vf_info->input_elem_descs[i].InstanceDataStepRate = 1;
D3D12_INPUT_ELEMENT_DESC &input_element_desc = vf_info->input_elem_descs[i];
const VertexAttribute &vertex_attrib = p_vertex_attribs[i];
const VertexAttributeBinding &vertex_binding = p_vertex_bindings[vertex_attrib.binding];

input_element_desc = {};
input_element_desc.SemanticName = "TEXCOORD";
input_element_desc.SemanticIndex = vertex_attrib.location;
input_element_desc.Format = RD_TO_D3D12_FORMAT[vertex_attrib.format].general_format;
input_element_desc.InputSlot = vertex_attrib.binding;
input_element_desc.AlignedByteOffset = vertex_attrib.offset;
if (vertex_binding.frequency == VERTEX_FREQUENCY_INSTANCE) {
input_element_desc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
input_element_desc.InstanceDataStepRate = 1;
} else {
vf_info->input_elem_descs[i].InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
vf_info->input_elem_descs[i].InstanceDataStepRate = 0;
input_element_desc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
input_element_desc.InstanceDataStepRate = 0;
}

vf_info->vertex_buffer_strides[i] = p_vertex_attribs[i].stride;
max_binding = MAX(max_binding, vertex_attrib.binding + 1);
}

vf_info->vertex_buffer_strides.resize(max_binding);
for (const VertexAttributeBindingsMap::KV &vertex_binding_pair : p_vertex_bindings) {
vf_info->vertex_buffer_strides[vertex_binding_pair.key] = vertex_binding_pair.value.stride;
}

return VertexFormatID(vf_info);
Expand Down Expand Up @@ -5378,7 +5405,7 @@ void RenderingDeviceDriverD3D12::command_render_draw_indirect_count(CommandBuffe
cmd_buf_info->cmd_list->ExecuteIndirect(indirect_cmd_signatures.draw.Get(), p_max_draw_count, indirect_buf_info->resource, p_offset, count_buf_info->resource, p_count_buffer_offset);
}

void RenderingDeviceDriverD3D12::command_render_bind_vertex_buffers(CommandBufferID p_cmd_buffer, uint32_t p_binding_count, const BufferID *p_buffers, const uint64_t *p_offsets) {
void RenderingDeviceDriverD3D12::command_render_bind_vertex_buffers(CommandBufferID p_cmd_buffer, uint32_t p_binding_count, const BufferID *p_buffers, const uint64_t *p_offsets, uint64_t p_dynamic_offsets) {
CommandBufferInfo *cmd_buf_info = (CommandBufferInfo *)p_cmd_buffer.id;

DEV_ASSERT(cmd_buf_info->render_pass_state.current_subpass != UINT32_MAX);
Expand All @@ -5390,8 +5417,15 @@ void RenderingDeviceDriverD3D12::command_render_bind_vertex_buffers(CommandBuffe
for (uint32_t i = 0; i < p_binding_count; i++) {
BufferInfo *buffer_info = (BufferInfo *)p_buffers[i].id;

uint32_t dynamic_offset = 0;
if (buffer_info->is_dynamic()) {
uint64_t buffer_frame_idx = p_dynamic_offsets & 0x3; // Assuming max 4 frames.
p_dynamic_offsets >>= 2;
dynamic_offset = buffer_frame_idx * buffer_info->size;
}

cmd_buf_info->render_pass_state.vertex_buffer_views[i] = {};
cmd_buf_info->render_pass_state.vertex_buffer_views[i].BufferLocation = buffer_info->resource->GetGPUVirtualAddress() + p_offsets[i];
cmd_buf_info->render_pass_state.vertex_buffer_views[i].BufferLocation = buffer_info->resource->GetGPUVirtualAddress() + dynamic_offset + p_offsets[i];
cmd_buf_info->render_pass_state.vertex_buffer_views[i].SizeInBytes = buffer_info->size - p_offsets[i];
if (!barrier_capabilities.enhanced_barriers_supported) {
_resource_transition_batch(cmd_buf_info, buffer_info, 0, 1, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
Expand Down
5 changes: 3 additions & 2 deletions drivers/d3d12/rendering_device_driver_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
virtual uint8_t *buffer_map(BufferID p_buffer) override final;
virtual void buffer_unmap(BufferID p_buffer) override final;
virtual uint8_t *buffer_persistent_map_advance(BufferID p_buffer, uint64_t p_frames_drawn) override final;
virtual uint64_t buffer_get_dynamic_offsets(Span<BufferID> p_buffers) override final;
virtual uint64_t buffer_get_device_address(BufferID p_buffer) override final;

/*****************/
Expand Down Expand Up @@ -429,7 +430,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
};

public:
virtual VertexFormatID vertex_format_create(VectorView<VertexAttribute> p_vertex_attribs) override final;
virtual VertexFormatID vertex_format_create(Span<VertexAttribute> p_vertex_attribs, const VertexAttributeBindingsMap &p_vertex_bindings) override final;
virtual void vertex_format_free(VertexFormatID p_vertex_format) override final;

/******************/
Expand Down Expand Up @@ -862,7 +863,7 @@ class RenderingDeviceDriverD3D12 : public RenderingDeviceDriver {
virtual void command_render_draw_indirect_count(CommandBufferID p_cmd_buffer, BufferID p_indirect_buffer, uint64_t p_offset, BufferID p_count_buffer, uint64_t p_count_buffer_offset, uint32_t p_max_draw_count, uint32_t p_stride) override final;

// Buffer binding.
virtual void command_render_bind_vertex_buffers(CommandBufferID p_cmd_buffer, uint32_t p_binding_count, const BufferID *p_buffers, const uint64_t *p_offsets) override final;
virtual void command_render_bind_vertex_buffers(CommandBufferID p_cmd_buffer, uint32_t p_binding_count, const BufferID *p_buffers, const uint64_t *p_offsets, uint64_t p_dynamic_offsets) override final;
virtual void command_render_bind_index_buffer(CommandBufferID p_cmd_buffer, BufferID p_buffer, IndexBufferFormat p_format, uint64_t p_offset) override final;

private:
Expand Down
2 changes: 1 addition & 1 deletion drivers/metal/metal_objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) MDCommandBuffer {
uint32_t p_instance_count,
uint32_t p_base_vertex,
uint32_t p_first_instance);
void render_bind_vertex_buffers(uint32_t p_binding_count, const RDD::BufferID *p_buffers, const uint64_t *p_offsets);
void render_bind_vertex_buffers(uint32_t p_binding_count, const RDD::BufferID *p_buffers, const uint64_t *p_offsets, uint64_t p_dynamic_offsets);
void render_bind_index_buffer(RDD::BufferID p_buffer, RDD::IndexBufferFormat p_format, uint64_t p_offset);

void render_draw_indexed(uint32_t p_index_count,
Expand Down
47 changes: 37 additions & 10 deletions drivers/metal/metal_objects.mm
Original file line number Diff line number Diff line change
Expand Up @@ -783,10 +783,12 @@ static bool isArrayTexture(MTLTextureType p_type) {

if (render.dirty.has_flag(RenderState::DIRTY_VERTEX)) {
uint32_t p_binding_count = render.vertex_buffers.size();
uint32_t first = device_driver->get_metal_buffer_index_for_vertex_attribute_binding(p_binding_count - 1);
[render.encoder setVertexBuffers:render.vertex_buffers.ptr()
offsets:render.vertex_offsets.ptr()
withRange:NSMakeRange(first, p_binding_count)];
if (p_binding_count > 0) {
uint32_t first = device_driver->get_metal_buffer_index_for_vertex_attribute_binding(p_binding_count - 1);
[render.encoder setVertexBuffers:render.vertex_buffers.ptr()
offsets:render.vertex_offsets.ptr()
withRange:NSMakeRange(first, p_binding_count)];
}
}

render.resource_tracker.encode(render.encoder);
Expand Down Expand Up @@ -1252,24 +1254,47 @@ static bool isArrayTexture(MTLTextureType p_type) {
baseInstance:p_first_instance];
}

void MDCommandBuffer::render_bind_vertex_buffers(uint32_t p_binding_count, const RDD::BufferID *p_buffers, const uint64_t *p_offsets) {
void MDCommandBuffer::render_bind_vertex_buffers(uint32_t p_binding_count, const RDD::BufferID *p_buffers, const uint64_t *p_offsets, uint64_t p_dynamic_offsets) {
DEV_ASSERT(type == MDCommandBufferStateType::Render);

render.vertex_buffers.resize(p_binding_count);
render.vertex_offsets.resize(p_binding_count);

// Are the existing buffer bindings the same?
bool same = true;

// Reverse the buffers, as their bindings are assigned in descending order.
for (uint32_t i = 0; i < p_binding_count; i += 1) {
const RenderingDeviceDriverMetal::BufferInfo *buf_info = (const RenderingDeviceDriverMetal::BufferInfo *)p_buffers[p_binding_count - i - 1].id;
render.vertex_buffers[i] = buf_info->metal_buffer;
render.vertex_offsets[i] = p_offsets[p_binding_count - i - 1];

NSUInteger dynamic_offset = 0;
if (buf_info->is_dynamic()) {
const MetalBufferDynamicInfo *dyn_buf = (const MetalBufferDynamicInfo *)buf_info;
uint64_t frame_idx = p_dynamic_offsets & 0x3;
p_dynamic_offsets >>= 2;
dynamic_offset = frame_idx * dyn_buf->size_bytes;
}
if (render.vertex_buffers[i] != buf_info->metal_buffer) {
render.vertex_buffers[i] = buf_info->metal_buffer;
same = false;
}

render.vertex_offsets[i] = dynamic_offset + p_offsets[p_binding_count - i - 1];
}

if (render.encoder) {
uint32_t first = device_driver->get_metal_buffer_index_for_vertex_attribute_binding(p_binding_count - 1);
[render.encoder setVertexBuffers:render.vertex_buffers.ptr()
offsets:render.vertex_offsets.ptr()
withRange:NSMakeRange(first, p_binding_count)];
if (same) {
NSUInteger *offset_ptr = render.vertex_offsets.ptr();
for (uint32_t i = first; i < first + p_binding_count; i++) {
[render.encoder setVertexBufferOffset:*offset_ptr atIndex:i];
offset_ptr++;
}
} else {
[render.encoder setVertexBuffers:render.vertex_buffers.ptr()
offsets:render.vertex_offsets.ptr()
withRange:NSMakeRange(first, p_binding_count)];
}
render.dirty.clear_flag(RenderState::DIRTY_VERTEX);
} else {
render.dirty.set_flag(RenderState::DIRTY_VERTEX);
Expand Down Expand Up @@ -1394,7 +1419,9 @@ static bool isArrayTexture(MTLTextureType p_type) {
viewports.clear();
scissors.clear();
blend_constants.reset();
bzero(vertex_buffers.ptr(), sizeof(id<MTLBuffer> __unsafe_unretained) * vertex_buffers.size());
vertex_buffers.clear();
bzero(vertex_offsets.ptr(), sizeof(NSUInteger) * vertex_offsets.size());
vertex_offsets.clear();
resource_tracker.reset();
}
Expand Down
5 changes: 3 additions & 2 deletions drivers/metal/rendering_device_driver_metal.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) RenderingDeviceDriverMet
virtual uint8_t *buffer_map(BufferID p_buffer) override final;
virtual void buffer_unmap(BufferID p_buffer) override final;
virtual uint8_t *buffer_persistent_map_advance(BufferID p_buffer, uint64_t p_frames_drawn) override final;
virtual uint64_t buffer_get_dynamic_offsets(Span<BufferID> p_buffers) override final;
virtual void buffer_flush(BufferID p_buffer) override final;
virtual uint64_t buffer_get_device_address(BufferID p_buffer) override final;

Expand Down Expand Up @@ -164,7 +165,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) RenderingDeviceDriverMet

private:
public:
virtual VertexFormatID vertex_format_create(VectorView<VertexAttribute> p_vertex_attribs) override final;
virtual VertexFormatID vertex_format_create(Span<VertexAttribute> p_vertex_attribs, const VertexAttributeBindingsMap &p_vertex_bindings) override final;
virtual void vertex_format_free(VertexFormatID p_vertex_format) override final;

#pragma mark - Barriers
Expand Down Expand Up @@ -403,7 +404,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) RenderingDeviceDriverMet
virtual void command_render_draw_indirect_count(CommandBufferID p_cmd_buffer, BufferID p_indirect_buffer, uint64_t p_offset, BufferID p_count_buffer, uint64_t p_count_buffer_offset, uint32_t p_max_draw_count, uint32_t p_stride) override final;

// Buffer binding.
virtual void command_render_bind_vertex_buffers(CommandBufferID p_cmd_buffer, uint32_t p_binding_count, const BufferID *p_buffers, const uint64_t *p_offsets) override final;
virtual void command_render_bind_vertex_buffers(CommandBufferID p_cmd_buffer, uint32_t p_binding_count, const BufferID *p_buffers, const uint64_t *p_offsets, uint64_t p_dynamic_offsets) override final;
virtual void command_render_bind_index_buffer(CommandBufferID p_cmd_buffer, BufferID p_buffer, IndexBufferFormat p_format, uint64_t p_offset) override final;

// Dynamic state.
Expand Down
Loading