Skip to content

Commit

Permalink
feat(dxmt): dependency tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
3Shain committed Dec 10, 2024
1 parent b4b8ce9 commit 9cb859a
Show file tree
Hide file tree
Showing 11 changed files with 229 additions and 48 deletions.
15 changes: 13 additions & 2 deletions src/d3d11/d3d11_context_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3234,8 +3234,8 @@ template <typename ContextInternalState> class MTLD3D11DeviceContextImplBase : p
}

Emit([rtvs = std::move(rtvs), dsv = std::move(dsv_info), effective_render_target, uav_only,
uav_only_render_target_height, uav_only_render_target_width, uav_only_sample_count,
render_target_array](ArgumentEncodingContext &ctx) {
uav_only_render_target_height, uav_only_render_target_width, uav_only_sample_count,
render_target_array](ArgumentEncodingContext &ctx) {
auto pool = transfer(NS::AutoreleasePool::alloc()->init());
auto renderPassDescriptor = transfer(MTL::RenderPassDescriptor::alloc()->init());
for (auto &rtv : rtvs.span()) {
Expand Down Expand Up @@ -3290,6 +3290,17 @@ template <typename ContextInternalState> class MTLD3D11DeviceContextImplBase : p
renderPassDescriptor->setRenderTargetArrayLength(render_target_array);

ctx.startRenderPass(std::move(renderPassDescriptor), dsv_planar_flags, rtvs.size());

for (auto &rtv : rtvs.span()) {
if (rtv.PixelFormat == MTL::PixelFormatInvalid) {
continue;
}
ctx.access(rtv.Texture, rtv.viewId, DXMT_ENCODER_RESOURCE_ACESS_READ | DXMT_ENCODER_RESOURCE_ACESS_WRITE);
};

if (dsv.Texture.ptr()) {
ctx.access(dsv.Texture, dsv.viewId, DXMT_ENCODER_RESOURCE_ACESS_READ | DXMT_ENCODER_RESOURCE_ACESS_WRITE);
}
});
}

Expand Down
3 changes: 3 additions & 0 deletions src/dxmt/dxmt_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

namespace dxmt {

std::atomic_uint64_t global_buffer_seq = {0};

BufferAllocation::BufferAllocation(Obj<MTL::Buffer> &&buffer, Flags<BufferAllocationFlag> flags) :
obj_(std::move(buffer)),
flags_(flags) {
Expand All @@ -17,6 +19,7 @@ BufferAllocation::BufferAllocation(Obj<MTL::Buffer> &&buffer, Flags<BufferAlloca
else
mappedMemory = obj_->contents();
gpuAddress = obj_->gpuAddress();
depkey = EncoderDepSet::generateNewKey(global_buffer_seq.fetch_add(1));
};

void
Expand Down
4 changes: 3 additions & 1 deletion src/dxmt/dxmt_buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "Metal/MTLDevice.hpp"
#include "Metal/MTLPixelFormat.hpp"
#include "Metal/MTLTexture.hpp"
#include "dxmt_deptrack.hpp"
#include "dxmt_residency.hpp"
#include "objc_pointer.hpp"
#include "rc/util_rc_ptr.hpp"
Expand Down Expand Up @@ -49,13 +50,14 @@ class BufferAllocation {
}

Flags<BufferAllocationFlag>
flags() {
flags() const {
return flags_;
}

void* mappedMemory;
uint64_t gpuAddress;
DXMT_RESOURCE_RESIDENCY_STATE residencyState;
EncoderDepKey depkey;

private:
BufferAllocation(Obj<MTL::Buffer> &&buffer, Flags<BufferAllocationFlag> flags);
Expand Down
114 changes: 78 additions & 36 deletions src/dxmt/dxmt_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ ArgumentEncodingContext::clearColor(
encoder_info->color = color;
encoder_info->array_length = arrayLength;

encoder_info->tex_write.add(texture->current()->depkey);

encoder_current = encoder_info;
endPass();
}
Expand All @@ -291,11 +293,13 @@ ArgumentEncodingContext::clearDepthStencil(
auto encoder_info = allocate<ClearEncoderData>();
encoder_info->type = EncoderType::Clear;
encoder_info->id = nextEncoderId();
encoder_info->clear_dsv = flag;
encoder_info->clear_dsv = flag & DepthStencilPlanarFlags(texture->pixelFormat());;
encoder_info->texture = texture->view(viewId);
encoder_info->depth_stencil = {depth, stencil};
encoder_info->array_length = arrayLength;

encoder_info->tex_write.add(texture->current()->depkey);

encoder_current = encoder_info;
endPass();
}
Expand All @@ -314,6 +318,9 @@ ArgumentEncodingContext::resolveTexture(
encoder_info->dst_slice = dstSlice;
encoder_info->dst_level = dstLevel;

encoder_info->tex_read.add(src->current()->depkey);
encoder_info->tex_write.add(dst->current()->depkey);

encoder_current = encoder_info;
endPass();
};
Expand All @@ -328,6 +335,8 @@ ArgumentEncodingContext::present(Rc<Texture> &texture, CA::MetalDrawable *drawab
encoder_info->drawable = drawable;
encoder_info->after = after;

encoder_info->tex_read.add(texture->current()->depkey);

encoder_current = encoder_info;
endPass();
}
Expand Down Expand Up @@ -420,6 +429,8 @@ ArgumentEncodingContext::bumpVisibilityResultOffset() {
}
}

constexpr unsigned kEncoderOptimizerThreshold = 64;

std::unique_ptr<VisibilityResultReadback>
ArgumentEncodingContext::flushCommands(MTL::CommandBuffer *cmdbuf, uint64_t seqId) {
assert(!encoder_current);
Expand All @@ -441,23 +452,15 @@ ArgumentEncodingContext::flushCommands(MTL::CommandBuffer *cmdbuf, uint64_t seqI

if (encoder_count > 1) {
unsigned j, i;
EncoderData *prev;
for (j = 0; j < encoder_count - 1; j++) {
prev = encoders[j];
if (prev->type == EncoderType::Null)
for (j = encoder_count - 2; j > 0; j--) {
if (encoders[j]->type == EncoderType::Null)
continue;
for (i = j + 1; i < encoder_count; i++) {
switch (checkEncoderRelation(prev, encoders[i])) {
case DXMT_ENCODER_LIST_OP_SYNCHRONIZE:
goto end;
case DXMT_ENCODER_LIST_OP_SWAP:
for (i = j + 1; i < std::min(encoder_count, j + kEncoderOptimizerThreshold); i++) {
if (encoders[i]->type == EncoderType::Null)
continue;
if (checkEncoderRelation(encoders[j], encoders[i]) == DXMT_ENCODER_LIST_OP_SYNCHRONIZE)
break;
case DXMT_ENCODER_LIST_OP_COALESCE:
prev->type = EncoderType::Null;
goto end;
}
}
end:;
}
}

Expand Down Expand Up @@ -536,14 +539,11 @@ ArgumentEncodingContext::flushCommands(MTL::CommandBuffer *cmdbuf, uint64_t seqI
}
case EncoderType::Clear: {
auto data = static_cast<ClearEncoderData *>(current);
if (data->skipped)
break;
{
auto enc_descriptor = MTL::RenderPassDescriptor::renderPassDescriptor();
MTL::Texture *texture = data->texture;
if (data->clear_dsv) {
uint32_t planar_flags = DepthStencilPlanarFlags(texture->pixelFormat());
if (data->clear_dsv & planar_flags & 1) {
if (data->clear_dsv & 1) {
auto attachmentz = enc_descriptor->depthAttachment();
attachmentz->setClearDepth(data->depth_stencil.first);
attachmentz->setTexture(texture);
Expand All @@ -553,7 +553,7 @@ ArgumentEncodingContext::flushCommands(MTL::CommandBuffer *cmdbuf, uint64_t seqI
attachmentz->setLevel(0);
attachmentz->setDepthPlane(0);
}
if (data->clear_dsv & planar_flags & 2) {
if (data->clear_dsv & 2) {
auto attachmentz = enc_descriptor->stencilAttachment();
attachmentz->setClearStencil(data->depth_stencil.second);
attachmentz->setTexture(texture);
Expand Down Expand Up @@ -632,33 +632,59 @@ ArgumentEncodingContext::checkEncoderRelation(EncoderData *former, EncoderData *

if (clear->clear_dsv) {
if (auto depth_attachment = isClearDepthSignatureMatched(clear, render)) {
depth_attachment->setClearDepth(clear->depth_stencil.first);
depth_attachment->setLoadAction(MTL::LoadActionClear);
if (depth_attachment->loadAction() == MTL::LoadActionLoad) {
depth_attachment->setClearDepth(clear->depth_stencil.first);
depth_attachment->setLoadAction(MTL::LoadActionClear);
if (depth_attachment->storeAction() != MTL::StoreActionDontCare)
render->tex_write.merge(clear->tex_write);
}
clear->clear_dsv &= ~1;
}
if (auto stencil_attachment = isClearStencilSignatureMatched(clear, render)) {
stencil_attachment->setClearStencil(clear->depth_stencil.second);
stencil_attachment->setLoadAction(MTL::LoadActionClear);
if (stencil_attachment->loadAction() == MTL::LoadActionLoad) {
stencil_attachment->setClearStencil(clear->depth_stencil.second);
stencil_attachment->setLoadAction(MTL::LoadActionClear);
if (stencil_attachment->storeAction() != MTL::StoreActionDontCare)
render->tex_write.merge(clear->tex_write);
}
clear->clear_dsv &= ~2;
}
if (clear->clear_dsv == 0) {
clear->~ClearEncoderData();
clear->next = nullptr;
clear->type = EncoderType::Null;
return DXMT_ENCODER_LIST_OP_COALESCE;
return DXMT_ENCODER_LIST_OP_SYNCHRONIZE;
}
} else {
if (auto attachment = isClearColorSignatureMatched(clear, render)) {
attachment->setLoadAction(MTL::LoadActionClear);
attachment->setClearColor(clear->color);
if (attachment->loadAction() == MTL::LoadActionLoad) {
attachment->setLoadAction(MTL::LoadActionClear);
attachment->setClearColor(clear->color);
if (attachment->storeAction() != MTL::StoreActionDontCare)
render->tex_write.merge(clear->tex_write);
}

clear->~ClearEncoderData();
clear->next = nullptr;
clear->type = EncoderType::Null;
return DXMT_ENCODER_LIST_OP_COALESCE;
return DXMT_ENCODER_LIST_OP_SYNCHRONIZE;
}
}
break;
}
if (latter->type == EncoderType::Clear && former->type == EncoderType::Render) {
auto render = reinterpret_cast<RenderEncoderData *>(former);
auto clear = reinterpret_cast<ClearEncoderData *>(latter);

if (clear->clear_dsv) {
if (render->descriptor->depthAttachment()->texture() == clear->texture.ptr()) {
render->descriptor->depthAttachment()->setStoreAction(MTL::StoreActionDontCare);
}
if (render->descriptor->stencilAttachment()->texture() == clear->texture.ptr()) {
render->descriptor->stencilAttachment()->setStoreAction(MTL::StoreActionDontCare);
}
}
}
return hasDataDependency(latter, former) ? DXMT_ENCODER_LIST_OP_SYNCHRONIZE : DXMT_ENCODER_LIST_OP_SWAP;
}

Expand Down Expand Up @@ -686,11 +712,16 @@ ArgumentEncodingContext::checkEncoderRelation(EncoderData *former, EncoderData *
r1->use_tessellation = r0->use_tessellation || r1->use_tessellation;
r1->use_visibility_result = r0->use_visibility_result || r1->use_visibility_result;

r1->buf_read.merge(r0->buf_read);
r1->buf_write.merge(r0->buf_write);
r1->tex_read.merge(r0->tex_read);
r1->tex_write.merge(r0->tex_write);

r0->~RenderEncoderData();
r0->next = nullptr;
r0->type = EncoderType::Null;

return DXMT_ENCODER_LIST_OP_COALESCE;
return DXMT_ENCODER_LIST_OP_SYNCHRONIZE;
}
}

Expand All @@ -700,10 +731,25 @@ ArgumentEncodingContext::checkEncoderRelation(EncoderData *former, EncoderData *
bool
ArgumentEncodingContext::hasDataDependency(EncoderData *latter, EncoderData *former) {
if (latter->type == EncoderType::Clear && former->type == EncoderType::Clear) {
// FIXME: potential bug: when the clear target is the same
// FIXME: prove it's safe to return false
return false;
}
return true; // TODO
// read-after-write
if (!former->buf_write.isDisjointWith(latter->buf_read))
return true;
if (!former->tex_write.isDisjointWith(latter->tex_read))
return true;
// write-after-write
if (!former->buf_write.isDisjointWith(latter->buf_write))
return true;
if (!former->tex_write.isDisjointWith(latter->tex_write))
return true;
// write-after-read
if (!former->buf_read.isDisjointWith(latter->buf_write))
return true;
if (!former->tex_read.isDisjointWith(latter->tex_write))
return true;
return false;
}

bool
Expand Down Expand Up @@ -740,7 +786,7 @@ MTL::RenderPassColorAttachmentDescriptor *
ArgumentEncodingContext::isClearColorSignatureMatched(ClearEncoderData *clear, RenderEncoderData *render) {
for (unsigned i = 0; i < render->render_target_count; i++) {
auto attachment = render->descriptor->colorAttachments()->object(i);
if (attachment->texture() == clear->texture.ptr() && attachment->loadAction() == MTL::LoadActionLoad) {
if (attachment->texture() == clear->texture.ptr()) {
return attachment;
}
}
Expand All @@ -754,8 +800,6 @@ ArgumentEncodingContext::isClearDepthSignatureMatched(ClearEncoderData *clear, R
auto depth_attachment = render->descriptor->depthAttachment();
if (depth_attachment->texture() != clear->texture.ptr())
return nullptr;
if (depth_attachment->loadAction() != MTL::LoadActionLoad)
return nullptr;
return depth_attachment;
}

Expand All @@ -766,8 +810,6 @@ ArgumentEncodingContext::isClearStencilSignatureMatched(ClearEncoderData *clear,
auto stencil_attachment = render->descriptor->stencilAttachment();
if (stencil_attachment->texture() != clear->texture.ptr())
return nullptr;
if (stencil_attachment->loadAction() != MTL::LoadActionLoad)
return nullptr;
return stencil_attachment;
}

Expand Down
Loading

0 comments on commit 9cb859a

Please sign in to comment.