diff --git a/src/d3d11/d3d11_context_impl.cpp b/src/d3d11/d3d11_context_impl.cpp index 13a8e6bc..490d6807 100644 --- a/src/d3d11/d3d11_context_impl.cpp +++ b/src/d3d11/d3d11_context_impl.cpp @@ -689,7 +689,7 @@ template class MTLD3D11DeviceContextImplBase : p EmitOP([=, texture = pUAV->texture(), viewId = pUAV->viewId(), value = std::array({Values[0], Values[1], Values[2], Values[3]}), dimension = desc.ViewDimension](ArgumentEncodingContext &enc) mutable { - auto view_format = texture->view(viewId).pixelFormat(); + auto view_format = texture->pixelFormat(viewId); auto uint_format = MTLGetUnsignedIntegerFormat((WMTPixelFormat)view_format); /* RG11B10Float is a special case */ if (view_format == WMTPixelFormatRG11B10Float) { @@ -937,7 +937,7 @@ template class MTLD3D11DeviceContextImplBase : p if (tex->pixelFormat(viewId) == WMTPixelFormatA8Unorm) { fixedViewId = tex->checkViewUseFormat(viewId, WMTPixelFormatR8Unorm); } - WMT::Texture texture = enc.access(tex, fixedViewId, DXMT_ENCODER_RESOURCE_ACESS_READ | DXMT_ENCODER_RESOURCE_ACESS_WRITE).texture; + WMT::Texture texture = enc.access(tex, fixedViewId, DXMT_ENCODER_RESOURCE_ACESS_READWRITE).texture; if (texture.mipmapLevelCount() > 1) { auto &cmd = enc.encodeBlitCommand(); cmd.type = WMTBlitCommandGenerateMipmaps; @@ -3908,7 +3908,7 @@ template class MTLD3D11DeviceContextImplBase : p SwitchToBlitEncoder(CommandBufferState::UpdateBlitEncoderActive); EmitOP([=, src = std::move(src), dst = std::move(dst), cmd = std::move(cmd)](ArgumentEncodingContext &enc) { - auto [src_buffer, src_offset] = enc.access(src, DXMT_ENCODER_RESOURCE_ACESS_READ); + auto [src_buffer, src_offset] = enc.access(src, 0, src->length(), DXMT_ENCODER_RESOURCE_ACESS_READ); auto texture = enc.access(dst, cmd.Dst.MipLevel, cmd.Dst.ArraySlice, DXMT_ENCODER_RESOURCE_ACESS_WRITE); auto &cmd_cptex = enc.encodeBlitCommand(); cmd_cptex.type = WMTBlitCommandCopyFromBufferToTexture; @@ -4156,34 +4156,36 @@ template class MTLD3D11DeviceContextImplBase : p render_target_array, encoder_argbuf_size = std::move(allocated_encoder_argbuf_size)](ArgumentEncodingContext &ctx) { auto pool = WMT::MakeAutoreleasePool(); uint32_t dsv_planar_flags = DepthStencilPlanarFlags(dsv.PixelFormat); - auto& info = ctx.startRenderPass(dsv_planar_flags, dsv.ReadOnlyFlags, rtvs.size(), *encoder_argbuf_size.get())->info; + auto& info = *ctx.startRenderPass(dsv_planar_flags, dsv.ReadOnlyFlags, rtvs.size(), *encoder_argbuf_size.get()); for (auto &rtv : rtvs.span()) { if (rtv.PixelFormat == WMTPixelFormatInvalid) { continue; } - auto& colorAttachment = info.colors[rtv.RenderTargetIndex]; - colorAttachment.texture = rtv.Texture->view(rtv.viewId); - colorAttachment.depth_plane = rtv.DepthPlane; - colorAttachment.load_action = rtv.LoadAction; - colorAttachment.store_action = WMTStoreActionStore; + auto &color = info.colors[rtv.RenderTargetIndex]; + color.attachment = ctx.access(rtv.Texture, rtv.viewId, DXMT_ENCODER_RESOURCE_ACESS_READWRITE); + color.depth_plane = rtv.DepthPlane; + color.load_action = rtv.LoadAction; + color.store_action = WMTStoreActionStore; }; if (dsv.Texture.ptr()) { - WMT::Texture texture = dsv.Texture->view(dsv.viewId); + auto access_flag = ((dsv.ReadOnlyFlags & dsv_planar_flags) == dsv_planar_flags) + ? DXMT_ENCODER_RESOURCE_ACESS_READ + : DXMT_ENCODER_RESOURCE_ACESS_READWRITE; // TODO: ...should know more about store behavior (e.g. DiscardView) if (dsv_planar_flags & 1) { - auto& depthAttachment = info.depth; - depthAttachment.texture = texture; - depthAttachment.load_action = dsv.DepthLoadAction; - depthAttachment.store_action = WMTStoreActionStore; + auto &depth = info.depth; + depth.attachment = ctx.access(dsv.Texture, dsv.viewId, access_flag); + depth.load_action = dsv.DepthLoadAction; + depth.store_action = WMTStoreActionStore; } if (dsv_planar_flags & 2) { - auto& stencilAttachment = info.stencil; - stencilAttachment.texture = texture; - stencilAttachment.load_action = dsv.StencilLoadAction; - stencilAttachment.store_action = WMTStoreActionStore; + auto &stencil = info.stencil; + stencil.attachment = ctx.access(dsv.Texture, dsv.viewId, access_flag); + stencil.load_action = dsv.StencilLoadAction; + stencil.store_action = WMTStoreActionStore; } } if (effective_render_target == 0) { @@ -4195,20 +4197,6 @@ template class MTLD3D11DeviceContextImplBase : p info.render_target_height = render_target_height; info.render_target_width = render_target_width; info.render_target_array_length = render_target_array; - - for (auto &rtv : rtvs.span()) { - if (rtv.PixelFormat == WMTPixelFormatInvalid) { - continue; - } - ctx.access(rtv.Texture, rtv.viewId, DXMT_ENCODER_RESOURCE_ACESS_READ | DXMT_ENCODER_RESOURCE_ACESS_WRITE); - }; - - if (dsv.Texture.ptr()) { - if ((dsv.ReadOnlyFlags & dsv_planar_flags) == dsv_planar_flags) - ctx.access(dsv.Texture, dsv.viewId, DXMT_ENCODER_RESOURCE_ACESS_READ); - else - ctx.access(dsv.Texture, dsv.viewId, DXMT_ENCODER_RESOURCE_ACESS_READ | DXMT_ENCODER_RESOURCE_ACESS_WRITE); - } }); } diff --git a/src/dxmt/dxmt_command.cpp b/src/dxmt/dxmt_command.cpp index b0563acc..9f9467d4 100644 --- a/src/dxmt/dxmt_command.cpp +++ b/src/dxmt/dxmt_command.cpp @@ -180,17 +180,17 @@ ClearRenderTargetContext::begin(Rc texture, TextureViewKey view) { auto width = texture->width(view); auto height = texture->height(view); auto array_length = texture->arrayLength(view); - auto &pass_info = ctx_.startRenderPass(dsv_flag, 0, 1, 0)->info; + auto &pass_info = *ctx_.startRenderPass(dsv_flag, 0, 1, 0); if (dsv_flag) { auto &depth = pass_info.depth; - depth.texture = ctx_.access(texture, view, DXMT_ENCODER_RESOURCE_ACESS_WRITE).texture; + depth.attachment = ctx_.access(texture, view, DXMT_ENCODER_RESOURCE_ACESS_WRITE); depth.depth_plane = 0; depth.load_action = WMTLoadActionLoad; depth.store_action = WMTStoreActionStore; } else { auto &color = pass_info.colors[0]; - color.texture = ctx_.access(texture, view, DXMT_ENCODER_RESOURCE_ACESS_WRITE).texture; + color.attachment = ctx_.access(texture, view, DXMT_ENCODER_RESOURCE_ACESS_WRITE); color.depth_plane = 0; color.load_action = WMTLoadActionLoad; color.store_action = WMTStoreActionStore; @@ -242,7 +242,7 @@ ClearRenderTargetContext::clear( draw.vertex_start = 0; draw.vertex_count = 3; draw.base_instance = 0; - draw.instance_count = ctx_.currentRenderEncoder()->info.render_target_array_length; + draw.instance_count = ctx_.currentRenderEncoder()->render_target_array_length; } void @@ -343,15 +343,15 @@ DepthStencilBlitContext::copyFromBuffer( auto width = depth_stencil->width(view); auto height = depth_stencil->height(view); - auto &pass_info = ctx_.startRenderPass(0b11, 0, 0, 0)->info; + auto &pass_info = *ctx_.startRenderPass(0b11, 0, 0, 0); auto &depth = pass_info.depth; - depth.texture = ctx_.access(depth_stencil, view, DXMT_ENCODER_RESOURCE_ACESS_WRITE).texture; + depth.attachment = ctx_.access(depth_stencil, view, DXMT_ENCODER_RESOURCE_ACESS_WRITE); depth.depth_plane = 0; depth.load_action = WMTLoadActionLoad; depth.store_action = WMTStoreActionStore; auto &stencil = pass_info.stencil; - stencil.texture = depth.texture; + stencil.attachment = ctx_.access(depth_stencil, view, DXMT_ENCODER_RESOURCE_ACESS_WRITE); stencil.depth_plane = 0; stencil.load_action = WMTLoadActionLoad; stencil.store_action = WMTStoreActionStore; @@ -583,7 +583,7 @@ ClearResourceKernelContext::clear(uint32_t offset_x, uint32_t offset_y, uint32_t meta_temp_.size[1] = height; if (clearing_texture_) { - auto dst_ = ctx_.access(clearing_texture_, clearing_view_, DXMT_ENCODER_RESOURCE_ACESS_WRITE); + auto &dst_ = ctx_.access(clearing_texture_, clearing_view_, DXMT_ENCODER_RESOURCE_ACESS_WRITE); auto &settex = ctx_.encodeComputeCommand(); settex.type = WMTComputeCommandSetTexture; settex.texture = dst_.texture; diff --git a/src/dxmt/dxmt_context.cpp b/src/dxmt/dxmt_context.cpp index f6b9bcaf..bedab9e5 100644 --- a/src/dxmt/dxmt_context.cpp +++ b/src/dxmt/dxmt_context.cpp @@ -74,11 +74,11 @@ ArgumentEncodingContext::encodeVertexBuffers(uint32_t slot_mask, uint64_t offset entries[index++].length = 0; continue; } - auto length = buffer->length(); - auto [buffer_alloc, buffer_offset] = access(buffer, DXMT_ENCODER_RESOURCE_ACESS_READ); + auto valid_length = buffer->length() > state.offset ? buffer->length() - state.offset : 0; + auto [buffer_alloc, buffer_offset] = access(buffer, state.offset, valid_length, DXMT_ENCODER_RESOURCE_ACESS_READ); entries[index].buffer_handle = buffer_alloc->gpuAddress() + buffer_offset + state.offset; entries[index].stride = state.stride; - entries[index++].length = length > state.offset ? length - state.offset : 0; + entries[index++].length = valid_length; // FIXME: did we intended to use the whole buffer? makeResident(buffer.ptr()); }; @@ -151,8 +151,8 @@ ArgumentEncodingContext::encodeConstantBuffers(const MTL_SHADER_REFLECTION *refl continue; } auto argbuf = cbuf.buffer; - // FIXME: did we intended to use the whole buffer? - auto [argbuf_alloc, argbuf_offset] = access(argbuf, DXMT_ENCODER_RESOURCE_ACESS_READ); + auto valid_length = argbuf->length() > cbuf.offset ? argbuf->length() - cbuf.offset : 0; + auto [argbuf_alloc, argbuf_offset] = access(argbuf, cbuf.offset, valid_length, DXMT_ENCODER_RESOURCE_ACESS_READ); encoded_buffer[arg.StructurePtrOffset] = argbuf_alloc->gpuAddress() + argbuf_offset + cbuf.offset; makeResident(argbuf.ptr()); break; @@ -286,7 +286,7 @@ ArgumentEncodingContext::encodeShaderResources( assert(arg.Flags & MTL_SM50_SHADER_ARGUMENT_TEXTURE_MINLOD_CLAMP); auto viewIdChecked = srv.texture->checkViewUseArray(srv.viewId, arg.Flags & MTL_SM50_SHADER_ARGUMENT_TEXTURE_ARRAY); encoded_buffer[arg.StructurePtrOffset] = - access(srv.texture, viewIdChecked, DXMT_ENCODER_RESOURCE_ACESS_READ).gpu_resource_id; + access(srv.texture, viewIdChecked, DXMT_ENCODER_RESOURCE_ACESS_READ).gpuResourceID; encoded_buffer[arg.StructurePtrOffset + 1] = TextureMetadata(srv.texture->arrayLength(viewIdChecked), 0); makeResident(srv.texture.ptr(), viewIdChecked); } else { @@ -325,7 +325,7 @@ ArgumentEncodingContext::encodeShaderResources( } else if (uav.texture.ptr()) { assert(arg.Flags & MTL_SM50_SHADER_ARGUMENT_TEXTURE_MINLOD_CLAMP); auto viewIdChecked = uav.texture->checkViewUseArray(uav.viewId, arg.Flags & MTL_SM50_SHADER_ARGUMENT_TEXTURE_ARRAY); - encoded_buffer[arg.StructurePtrOffset] = access(uav.texture, viewIdChecked, access_flags).gpu_resource_id; + encoded_buffer[arg.StructurePtrOffset] = access(uav.texture, viewIdChecked, access_flags).gpuResourceID; encoded_buffer[arg.StructurePtrOffset + 1] = TextureMetadata(uav.texture->arrayLength(viewIdChecked), 0); makeResident(uav.texture.ptr(), viewIdChecked, read, write); } else { @@ -402,7 +402,7 @@ ArgumentEncodingContext::clearColor(Rc &&texture, unsigned viewId, unsi encoder_info->height = texture->height(); encoder_current = encoder_info; - encoder_info->texture = access(texture, viewId, DXMT_ENCODER_RESOURCE_ACESS_WRITE).texture; + encoder_info->attachment = access(texture, viewId, DXMT_ENCODER_RESOURCE_ACESS_WRITE); currentFrameStatistics().clear_pass_count++; @@ -424,7 +424,7 @@ ArgumentEncodingContext::clearDepthStencil( encoder_info->height = texture->height(); encoder_current = encoder_info; - encoder_info->texture = access(texture, viewId, DXMT_ENCODER_RESOURCE_ACESS_WRITE).texture; + encoder_info->attachment = access(texture, viewId, DXMT_ENCODER_RESOURCE_ACESS_WRITE); currentFrameStatistics().clear_pass_count++; @@ -440,8 +440,8 @@ ArgumentEncodingContext::resolveTexture( encoder_info->type = EncoderType::Resolve; encoder_current = encoder_info; - encoder_info->src = access(src, src_view, DXMT_ENCODER_RESOURCE_ACESS_READ).texture; - encoder_info->dst = access(dst, dst_view, DXMT_ENCODER_RESOURCE_ACESS_WRITE).texture; + encoder_info->src = access(src, src_view, DXMT_ENCODER_RESOURCE_ACESS_READ); + encoder_info->dst = access(dst, dst_view, DXMT_ENCODER_RESOURCE_ACESS_WRITE); endPass(); }; @@ -492,7 +492,7 @@ ArgumentEncodingContext::upscaleTemporal( encoder_info->input = input->current()->texture(); encoder_info->output = output->current()->texture(); encoder_info->depth = depth->current()->texture(); - encoder_info->motion_vector = motion_vector->view(mvViewId); + encoder_info->motion_vector = motion_vector->view(mvViewId).texture; encoder_info->scaler = scaler; encoder_info->props = props; @@ -558,7 +558,6 @@ ArgumentEncodingContext::startRenderPass( auto encoder_info = allocate(); encoder_info->type = EncoderType::Render; encoder_info->id = nextEncoderId(); - WMT::InitializeRenderPassInfo(encoder_info->info); encoder_info->cmd_head.type = WMTRenderCommandNop; encoder_info->cmd_head.next.set(0); encoder_info->cmd_tail = (wmtcmd_base *)&encoder_info->cmd_head; @@ -731,12 +730,58 @@ ArgumentEncodingContext::flushCommands(WMT::CommandBuffer cmdbuf, uint64_t seqId switch (current->type) { case EncoderType::Render: { auto data = static_cast(current); + WMTRenderPassInfo render_pass_info{}; + { + for (unsigned i = 0; i < std::size(render_pass_info.colors); i++) { + auto &color_data = data->colors[i]; + if (!color_data.attachment) + continue; + auto &color_info = render_pass_info.colors[i]; + color_info.texture = color_data.attachment.texture(); + color_info.load_action = color_data.load_action; + color_info.store_action = color_data.store_action; + color_info.level = color_data.level; + color_info.slice = color_data.slice; + color_info.depth_plane = color_data.depth_plane; + color_info.clear_color = color_data.clear_color; + color_info.resolve_texture = color_data.resolve_attachment.texture(); + color_info.resolve_level = color_data.resolve_level; + color_info.resolve_slice = color_data.resolve_slice; + color_info.resolve_depth_plane = color_data.resolve_depth_plane; + } + if (data->depth.attachment) { + auto &depth_info = render_pass_info.depth; + auto &depth_data = data->depth; + depth_info.texture = depth_data.attachment.texture(); + depth_info.load_action = depth_data.load_action; + depth_info.store_action = depth_data.store_action; + depth_info.level = depth_data.level; + depth_info.slice = depth_data.slice; + depth_info.depth_plane = depth_data.depth_plane; + depth_info.clear_depth = depth_data.clear_depth; + } + if (data->stencil.attachment) { + auto &stencil_info = render_pass_info.stencil; + auto &stencil_data = data->stencil; + stencil_info.texture = stencil_data.attachment.texture(); + stencil_info.load_action = stencil_data.load_action; + stencil_info.store_action = stencil_data.store_action; + stencil_info.level = stencil_data.level; + stencil_info.slice = stencil_data.slice; + stencil_info.depth_plane = stencil_data.depth_plane; + stencil_info.clear_stencil = stencil_data.clear_stencil; + } + render_pass_info.default_raster_sample_count = data->default_raster_sample_count; + render_pass_info.render_target_array_length = data->render_target_array_length; + render_pass_info.render_target_width = data->render_target_width; + render_pass_info.render_target_height = data->render_target_height; + } if (data->use_visibility_result) { assert(visibility_readback); - data->info.visibility_buffer = visibility_readback->visibility_result_heap; + render_pass_info.visibility_buffer = visibility_readback->visibility_result_heap; } auto gpu_buffer_ = data->allocated_argbuf; - auto encoder = cmdbuf.renderCommandEncoder(data->info); + auto encoder = cmdbuf.renderCommandEncoder(render_pass_info); encoder.setVertexBuffer(gpu_buffer_, 0, 16); encoder.setVertexBuffer(gpu_buffer_, 0, 29); encoder.setVertexBuffer(gpu_buffer_, 0, 30); @@ -863,13 +908,13 @@ ArgumentEncodingContext::flushCommands(WMT::CommandBuffer cmdbuf, uint64_t seqId if (data->clear_dsv) { if (data->clear_dsv & 1) { info.depth.clear_depth = data->depth_stencil.first; - info.depth.texture = data->texture; + info.depth.texture = data->attachment.texture(); info.depth.load_action = WMTLoadActionClear; info.depth.store_action = WMTStoreActionStore; } if (data->clear_dsv & 2) { info.stencil.clear_stencil = data->depth_stencil.second; - info.stencil.texture = data->texture; + info.stencil.texture = data->attachment.texture(); info.stencil.load_action = WMTLoadActionClear; info.stencil.store_action = WMTStoreActionStore; } @@ -877,7 +922,7 @@ ArgumentEncodingContext::flushCommands(WMT::CommandBuffer cmdbuf, uint64_t seqId info.render_target_height = data->height; } else { info.colors[0].clear_color = data->color; - info.colors[0].texture = data->texture; + info.colors[0].texture = data->attachment.texture(); info.colors[0].load_action = WMTLoadActionClear; info.colors[0].store_action = WMTStoreActionStore; } @@ -894,10 +939,10 @@ ArgumentEncodingContext::flushCommands(WMT::CommandBuffer cmdbuf, uint64_t seqId { WMTRenderPassInfo info; WMT::InitializeRenderPassInfo(info); - info.colors[0].texture = data->src; + info.colors[0].texture = data->src.texture(); info.colors[0].load_action = WMTLoadActionLoad; info.colors[0].store_action = WMTStoreActionStoreAndMultisampleResolve; - info.colors[0].resolve_texture = data->dst; + info.colors[0].resolve_texture = data->dst.texture(); auto encoder = cmdbuf.renderCommandEncoder(info); encoder.setLabel(WMT::String::string("ResolvePass", WMTUTF8StringEncoding)); @@ -970,7 +1015,7 @@ ArgumentEncodingContext::checkEncoderRelation(EncoderData *former, EncoderData * auto render = reinterpret_cast(latter); auto clear = reinterpret_cast(former); - if (render->info.render_target_array_length != clear->array_length) + if (render->render_target_array_length != clear->array_length) break; if (clear->clear_dsv) { @@ -1023,10 +1068,26 @@ ArgumentEncodingContext::checkEncoderRelation(EncoderData *former, EncoderData * // DontCare can be used because it's going to be cleared anyway // just keep in mind DontCare != DontStore - if (clear->clear_dsv & 1 && render->info.depth.texture == clear->texture.handle) - render->info.depth.store_action = WMTStoreActionDontCare; - if (clear->clear_dsv & 2 && render->info.stencil.texture == clear->texture.handle) - render->info.stencil.store_action = WMTStoreActionDontCare; + if (clear->clear_dsv & 1 && render->depth.attachment == clear->attachment) + render->depth.store_action = WMTStoreActionDontCare; + if (clear->clear_dsv & 2 && render->stencil.attachment == clear->attachment) + render->stencil.store_action = WMTStoreActionDontCare; + } + if (former->type == EncoderType::Render && latter->type == EncoderType::Resolve) { + auto render = reinterpret_cast(former); + auto resolve = reinterpret_cast(latter); + auto result = isResolveSignatureMatched(render, resolve); + if (result.src && result.src->store_action == WMTStoreActionStore) { + result.src->store_action = WMTStoreActionStoreAndMultisampleResolve; + result.src->resolve_attachment = result.dst; + render->tex_write.merge(resolve->tex_write); + + currentFrameStatistics().resolve_pass_optimized++; + resolve->~ResolveEncoderData(); + resolve->next = nullptr; + resolve->type = EncoderType::Null; + return DXMT_ENCODER_LIST_OP_SWAP; // carry on (RENDER -> RESOLVE -> RESOLVE -> ...) + } } return hasDataDependency(latter, former) ? DXMT_ENCODER_LIST_OP_SYNCHRONIZE : DXMT_ENCODER_LIST_OP_SWAP; } @@ -1037,18 +1098,18 @@ ArgumentEncodingContext::checkEncoderRelation(EncoderData *former, EncoderData * if (isEncoderSignatureMatched(r0, r1)) { for (unsigned i = 0; i < r0->render_target_count; i++) { - auto &a0 = r0->info.colors[i]; - auto &a1 = r1->info.colors[i]; + auto &a0 = r0->colors[i]; + auto &a1 = r1->colors[i]; a1.load_action = a0.load_action; a1.clear_color = a0.clear_color; } - r1->info.depth.load_action = r0->info.depth.load_action; - r1->info.depth.clear_depth = r0->info.depth.clear_depth; - r1->info.depth.store_action = r0->info.depth.store_action; - r1->info.stencil.load_action = r0->info.stencil.load_action; - r1->info.stencil.clear_stencil = r0->info.stencil.clear_stencil; - r1->info.stencil.store_action = r0->info.stencil.store_action; + r1->depth.load_action = r0->depth.load_action; + r1->depth.clear_depth = r0->depth.clear_depth; + r1->depth.store_action = r0->depth.store_action; + r1->stencil.load_action = r0->stencil.load_action; + r1->stencil.clear_stencil = r0->stencil.clear_stencil; + r1->stencil.store_action = r0->stencil.store_action; if ((void *)r0->cmd_tail != &r0->cmd_head) { r0->cmd_tail->next.set(r1->cmd_head.next.get()); @@ -1122,7 +1183,7 @@ ArgumentEncodingContext::isEncoderSignatureMatched(RenderEncoderData *r0, Render return false; if (r0->dsv_readonly_flags != r1->dsv_readonly_flags) return false; - if (r0->info.render_target_array_length != r1->info.render_target_array_length) + if (r0->render_target_array_length != r1->render_target_array_length) return false; /** In case two encoder has different argument buffer @@ -1132,39 +1193,39 @@ ArgumentEncodingContext::isEncoderSignatureMatched(RenderEncoderData *r0, Render if (r0->allocated_argbuf != r1->allocated_argbuf) return false; if (r0->dsv_planar_flags & 1) { - if (r0->info.depth.texture != r1->info.depth.texture) + if (r0->depth.attachment != r1->depth.attachment) return false; if (r0->dsv_readonly_flags & 1) { - if (r1->info.depth.load_action == WMTLoadActionClear) + if (r1->depth.load_action == WMTLoadActionClear) return false; } else { - if (r0->info.depth.store_action != WMTStoreActionStore) + if (r0->depth.store_action != WMTStoreActionStore) return false; - if (r1->info.depth.load_action != WMTLoadActionLoad) + if (r1->depth.load_action != WMTLoadActionLoad) return false; } } if (r0->dsv_planar_flags & 2) { - if (r0->info.stencil.texture != r1->info.stencil.texture) + if (r0->stencil.attachment != r1->stencil.attachment) return false; if (r0->dsv_readonly_flags & 2) { - if (r1->info.stencil.load_action == WMTLoadActionClear) + if (r1->stencil.load_action == WMTLoadActionClear) return false; } else { - if (r0->info.stencil.store_action != WMTStoreActionStore) + if (r0->stencil.store_action != WMTStoreActionStore) return false; - if (r1->info.stencil.load_action != WMTLoadActionLoad) + if (r1->stencil.load_action != WMTLoadActionLoad) return false; } } for (unsigned i = 0; i < r0->render_target_count; i++) { - auto &a0 = r0->info.colors[i]; - auto &a1 = r1->info.colors[i]; - if (a0.texture != a1.texture) + auto &a0 = r0->colors[i]; + auto &a1 = r1->colors[i]; + if (a0.attachment != a1.attachment) return false; if (a0.depth_plane != a1.depth_plane) return false; - if (!a0.texture) + if (!a0.attachment) continue; if (a0.store_action != WMTStoreActionStore) return false; @@ -1174,33 +1235,63 @@ ArgumentEncodingContext::isEncoderSignatureMatched(RenderEncoderData *r0, Render return true; } -WMTColorAttachmentInfo * +RenderEncoderColorAttachmentData * ArgumentEncodingContext::isClearColorSignatureMatched(ClearEncoderData *clear, RenderEncoderData *render) { for (unsigned i = 0; i < render->render_target_count; i++) { - auto &attachment = render->info.colors[i]; - if (attachment.texture == clear->texture.handle) { + auto &attachment = render->colors[i]; + if (attachment.attachment == clear->attachment) { return &attachment; } } return nullptr; } -WMTDepthAttachmentInfo * +RenderEncoderDepthAttachmentData * ArgumentEncodingContext::isClearDepthSignatureMatched(ClearEncoderData *clear, RenderEncoderData *render) { if ((clear->clear_dsv & 1) == 0) return nullptr; - if (render->info.depth.texture != clear->texture.handle) + if (render->depth.attachment != clear->attachment) return nullptr; - return &render->info.depth; + return &render->depth; } -WMTStencilAttachmentInfo * +RenderEncoderStencilAttachmentData * ArgumentEncodingContext::isClearStencilSignatureMatched(ClearEncoderData *clear, RenderEncoderData *render) { if ((clear->clear_dsv & 2) == 0) return nullptr; - if (render->info.stencil.texture != clear->texture.handle) + if (render->stencil.attachment != clear->attachment) return nullptr; - return &render->info.stencil; + return &render->stencil; +} + +ArgumentEncodingContext::ResolveSignatureMatchResult +ArgumentEncodingContext::isResolveSignatureMatched(RenderEncoderData *render, ResolveEncoderData *resolve) { + ResolveSignatureMatchResult ret{}; + for (unsigned i = 0; i < render->render_target_count; i++) { + auto &color = render->colors[i]; + if (color.resolve_attachment) + continue; + if (!color.attachment) + continue; + if (color.attachment->allocation != resolve->src->allocation) + continue; + if (color.attachment->key == resolve->src->key) { + ret.src = &color; + ret.dst = resolve->dst; + break; + }; + auto &descriptor_src = resolve->src->allocation->descriptor; + auto &descriptor_dst = resolve->dst->allocation->descriptor; + auto color_format = descriptor_src->pixelFormat(color.attachment->key); + auto view_src_in_color_format = descriptor_src->checkViewUseFormat(resolve->src->key, color_format); + if (color.attachment->key == view_src_in_color_format) { + auto view_dst_in_color_format = descriptor_dst->checkViewUseFormat(resolve->dst->key, color_format); + ret.src = &color; + ret.dst = descriptor_dst->view(view_dst_in_color_format, resolve->dst->allocation); + break; + } + } + return ret; } } // namespace dxmt \ No newline at end of file diff --git a/src/dxmt/dxmt_context.hpp b/src/dxmt/dxmt_context.hpp index c5810a08..2d27741e 100644 --- a/src/dxmt/dxmt_context.hpp +++ b/src/dxmt/dxmt_context.hpp @@ -119,8 +119,48 @@ struct TSDispatchArgumentsMarshal { uint32_t patch_per_group; }; +struct RenderEncoderColorAttachmentData { + TextureViewRef attachment; + enum WMTLoadAction load_action; + enum WMTStoreAction store_action; + uint16_t level; + uint16_t slice; + uint32_t depth_plane; + struct WMTClearColor clear_color; + TextureViewRef resolve_attachment; + uint16_t resolve_level; + uint16_t resolve_slice; + uint32_t resolve_depth_plane; +}; + +struct RenderEncoderDepthAttachmentData { + TextureViewRef attachment; + enum WMTLoadAction load_action; + enum WMTStoreAction store_action; + uint16_t level; + uint16_t slice; + uint32_t depth_plane; + float clear_depth; +}; + +struct RenderEncoderStencilAttachmentData : WMTStencilAttachmentInfo { + TextureViewRef attachment; + enum WMTLoadAction load_action; + enum WMTStoreAction store_action; + uint16_t level; + uint16_t slice; + uint32_t depth_plane; + uint8_t clear_stencil; +}; + struct RenderEncoderData : EncoderData { - WMTRenderPassInfo info; + RenderEncoderColorAttachmentData colors[8]; + RenderEncoderDepthAttachmentData depth; + RenderEncoderStencilAttachmentData stencil; + uint8_t default_raster_sample_count; + uint16_t render_target_array_length; + uint32_t render_target_height; + uint32_t render_target_width; std::vector gs_arg_marshal_tasks; std::vector ts_arg_marshal_tasks; wmtcmd_render_nop cmd_head; @@ -154,7 +194,7 @@ struct ClearEncoderData : EncoderData { WMTClearColor color; std::pair depth_stencil; }; - WMT::Reference texture; + TextureViewRef attachment; unsigned clear_dsv; unsigned array_length; unsigned width; @@ -164,8 +204,8 @@ struct ClearEncoderData : EncoderData { }; struct ResolveEncoderData : EncoderData { - WMT::Reference src; - WMT::Reference dst; + TextureViewRef src; + TextureViewRef dst; }; class Presenter; @@ -246,6 +286,7 @@ class CommandQueue; enum DXMT_ENCODER_RESOURCE_ACESS { DXMT_ENCODER_RESOURCE_ACESS_READ = 1 <<0, DXMT_ENCODER_RESOURCE_ACESS_WRITE = 1 << 1, + DXMT_ENCODER_RESOURCE_ACESS_READWRITE = DXMT_ENCODER_RESOURCE_ACESS_READ | DXMT_ENCODER_RESOURCE_ACESS_WRITE, }; struct AllocatedTempBufferSlice { @@ -293,13 +334,6 @@ class ArgumentEncodingContext { return {view, allocation->currentSuballocationOffset(view.suballocation_texel)}; } - std::pair - access(Rc const &buffer, DXMT_ENCODER_RESOURCE_ACESS flags) { - auto allocation = buffer->current(); - trackBuffer(allocation, flags); - return {allocation, allocation->currentSuballocationOffset()}; - } - WMT::Texture access(Rc const &texture, unsigned level, unsigned slice, DXMT_ENCODER_RESOURCE_ACESS flags) { auto allocation = texture->current(); @@ -307,18 +341,11 @@ class ArgumentEncodingContext { return allocation->texture(); } - TextureView const & + TextureView & access(Rc const &texture, unsigned viewId, DXMT_ENCODER_RESOURCE_ACESS flags) { auto allocation = texture->current(); trackTexture(allocation, flags); - return texture->view_(viewId, allocation); - } - - WMT::Texture - access(Rc const &texture, DXMT_ENCODER_RESOURCE_ACESS flags) { - auto allocation = texture->current(); - trackTexture(allocation, flags); - return allocation->texture(); + return texture->view(viewId, allocation); } template @@ -469,8 +496,9 @@ class ArgumentEncodingContext { auto allocation = texture->current(); uint64_t encoder_id = currentEncoder()->id; DXMT_RESOURCE_RESIDENCY requested = GetResidencyMask(stage, read, write); - if (CheckResourceResidency(texture->residency(viewId, allocation), encoder_id, requested)) { - makeResident(texture->view(viewId, allocation), requested); + auto &view = texture->view(viewId, allocation); + if (CheckResourceResidency(view.residency, encoder_id, requested)) { + makeResident(view.texture, requested); }; } @@ -695,9 +723,16 @@ class ArgumentEncodingContext { DXMT_ENCODER_LIST_OP checkEncoderRelation(EncoderData* former, EncoderData* latter); bool hasDataDependency(EncoderData* from, EncoderData* to); bool isEncoderSignatureMatched(RenderEncoderData* former, RenderEncoderData* latter); - WMTColorAttachmentInfo *isClearColorSignatureMatched(ClearEncoderData* former, RenderEncoderData* latter); - WMTDepthAttachmentInfo *isClearDepthSignatureMatched(ClearEncoderData* former, RenderEncoderData* latter); - WMTStencilAttachmentInfo *isClearStencilSignatureMatched(ClearEncoderData* former, RenderEncoderData* latter); + RenderEncoderColorAttachmentData *isClearColorSignatureMatched(ClearEncoderData* former, RenderEncoderData* latter); + RenderEncoderDepthAttachmentData *isClearDepthSignatureMatched(ClearEncoderData* former, RenderEncoderData* latter); + RenderEncoderStencilAttachmentData *isClearStencilSignatureMatched(ClearEncoderData* former, RenderEncoderData* latter); + + class ResolveSignatureMatchResult { + public: + RenderEncoderColorAttachmentData *src{}; + TextureViewRef dst{}; + }; + ResolveSignatureMatchResult isResolveSignatureMatched(RenderEncoderData *former, ResolveEncoderData *latter); std::array vbuf_; Rc ibuf_; diff --git a/src/dxmt/dxmt_statistics.hpp b/src/dxmt/dxmt_statistics.hpp index 7191c019..425d5ea6 100644 --- a/src/dxmt/dxmt_statistics.hpp +++ b/src/dxmt/dxmt_statistics.hpp @@ -45,6 +45,7 @@ struct FrameStatistics { uint32_t render_pass_optimized = 0; uint32_t clear_pass_count = 0; uint32_t clear_pass_optimized = 0; + uint32_t resolve_pass_optimized = 0; uint32_t compute_pass_count = 0; uint32_t blit_pass_count = 0; uint32_t event_stall = 0; @@ -66,6 +67,7 @@ struct FrameStatistics { render_pass_optimized = 0; clear_pass_count = 0; clear_pass_optimized = 0; + resolve_pass_optimized = 0; compute_pass_count = 0; blit_pass_count = 0; event_stall = 0; diff --git a/src/dxmt/dxmt_texture.cpp b/src/dxmt/dxmt_texture.cpp index 7c2bea67..a9fc5c69 100644 --- a/src/dxmt/dxmt_texture.cpp +++ b/src/dxmt/dxmt_texture.cpp @@ -8,10 +8,37 @@ namespace dxmt { std::atomic_uint64_t global_texture_seq = {0}; +void +TextureView::incRef() { + refcount_.fetch_add(1u, std::memory_order_acquire); +}; + +void +TextureView::decRef() { + if (refcount_.fetch_sub(1u, std::memory_order_release) == 1u) + delete this; +}; + +TextureView::TextureView(TextureAllocation *allocation) : + texture(allocation->texture()), + gpuResourceID(allocation->gpuResourceID), + allocation(allocation), + key(0) {} + +TextureView::TextureView(TextureAllocation *allocation, TextureViewKey key) : allocation(allocation), key(key) { + auto parent = allocation->texture(); + auto &view = allocation->descriptor->viewDescriptors_[key]; + texture = parent.newTextureView( + view.format, view.type, view.firstMiplevel, view.miplevelCount, view.firstArraySlice, view.arraySize, + {WMTTextureSwizzleRed, WMTTextureSwizzleGreen, WMTTextureSwizzleBlue, WMTTextureSwizzleAlpha}, gpuResourceID + ); +} + TextureAllocation::TextureAllocation( - WMT::Reference &&buffer, void *mapped_buffer, const WMTTextureInfo &info, unsigned bytes_per_row, - Flags flags + Texture *descriptor, WMT::Reference &&buffer, void *mapped_buffer, const WMTTextureInfo &info, + unsigned bytes_per_row, Flags flags ) : + descriptor(descriptor), mappedMemory(mapped_buffer), buffer_(std::move(buffer)), flags_(flags) { @@ -24,8 +51,10 @@ TextureAllocation::TextureAllocation( }; TextureAllocation::TextureAllocation( - WMT::Reference &&texture, const WMTTextureInfo &textureDescriptor, Flags flags + Texture *descriptor, WMT::Reference &&texture, const WMTTextureInfo &textureDescriptor, + Flags flags ) : + descriptor(descriptor), obj_(std::move(texture)), flags_(flags) { mappedMemory = nullptr; @@ -44,18 +73,11 @@ void Texture::prepareAllocationViews(TextureAllocation *allocaiton) { std::unique_lock lock(mutex_); if (allocaiton->version_ < 1) { - allocaiton->cached_view_.push_back(std::make_unique(allocaiton->obj_, allocaiton->gpuResourceID)); + allocaiton->cached_view_.push_back(new TextureView(allocaiton)); allocaiton->version_ = 1; } for (unsigned version = allocaiton->version_; version < version_; version++) { - auto &texture = allocaiton->obj_; - auto &view = viewDescriptors_[version]; - uint64_t gpu_resource_id; - WMT::Reference ref = texture.newTextureView( - view.format, view.type, view.firstMiplevel, view.miplevelCount, view.firstArraySlice, view.arraySize, - {WMTTextureSwizzleRed, WMTTextureSwizzleGreen, WMTTextureSwizzleBlue, WMTTextureSwizzleAlpha}, gpu_resource_id - ); - allocaiton->cached_view_.push_back(std::make_unique(std::move(ref), gpu_resource_id)); + allocaiton->cached_view_.push_back(new TextureView(allocaiton, version)); } allocaiton->version_ = version_; } @@ -159,10 +181,10 @@ Texture::allocate(Flags flags) { buffer_info.memory.set(wsi::aligned_malloc(bytes_per_image_, DXMT_PAGE_SIZE)); #endif auto buffer = device_.newBuffer(buffer_info); - return new TextureAllocation(std::move(buffer), buffer_info.memory.get(), info, bytes_per_row_, flags); + return new TextureAllocation(this, std::move(buffer), buffer_info.memory.get(), info, bytes_per_row_, flags); } auto texture = flags.test(TextureAllocationFlag::Shared) ? device_.newSharedTexture(info) : device_.newTexture(info); - return new TextureAllocation(std::move(texture), info, flags); + return new TextureAllocation(this, std::move(texture), info, flags); } Rc @@ -182,29 +204,19 @@ Texture::import(mach_port_t mach_port) { if (info.options & WMTResourceHazardTrackingModeUntracked) flags.set(TextureAllocationFlag::NoTracking); flags.set(TextureAllocationFlag::Shared); - return new TextureAllocation(std::move(texture), info, flags); + return new TextureAllocation(this, std::move(texture), info, flags); } assert(texture && "failed to import shared texture"); return nullptr; } -WMT::Texture +TextureView & Texture::view(TextureViewKey key) { return view(key, current_.ptr()); } -WMT::Texture +TextureView & Texture::view(TextureViewKey key, TextureAllocation* allocation) { - return view_(key, allocation).texture; -} - -TextureView const & -Texture::view_(TextureViewKey key) { - return view_(key, current_.ptr()); -} - -TextureView const & -Texture::view_(TextureViewKey key, TextureAllocation* allocation) { if (unlikely(allocation->version_ != version_)) { prepareAllocationViews(allocation); } @@ -269,19 +281,6 @@ TextureViewKey Texture::checkViewUseFormat(TextureViewKey key, WMTPixelFormat fo return key; } -DXMT_RESOURCE_RESIDENCY_STATE & -Texture::residency(TextureViewKey key) { - return residency(key, current_.ptr()); -} - -DXMT_RESOURCE_RESIDENCY_STATE & -Texture::residency(TextureViewKey key, TextureAllocation *allocation) { - if (unlikely(allocation->version_ != version_)) { - prepareAllocationViews(allocation); - } - return allocation->cached_view_[key]->residency; -} - Rc Texture::rename(Rc &&newAllocation) { Rc old = std::move(current_); diff --git a/src/dxmt/dxmt_texture.hpp b/src/dxmt/dxmt_texture.hpp index af1b7cd5..96c5b3a4 100644 --- a/src/dxmt/dxmt_texture.hpp +++ b/src/dxmt/dxmt_texture.hpp @@ -31,17 +31,48 @@ struct TextureViewDescriptor { unsigned arraySize = 1; }; -struct TextureView { +class Texture; +class TextureAllocation; + +class TextureView { +public: + virtual ~TextureView() {}; + + void incRef(); + void decRef(); + WMT::Reference texture; - uint64_t gpu_resource_id; + uint64_t gpuResourceID; DXMT_RESOURCE_RESIDENCY_STATE residency{}; + TextureAllocation *allocation; // `TextureAllocation` holds strong reference to `TextureView` + TextureViewKey key; + + TextureView(const TextureView &) = delete; + TextureView(TextureView &&) = delete; + TextureView &operator=(const TextureView &) = delete; + TextureView &operator=(TextureView &&) = delete; + TextureView(TextureAllocation * allocation); + TextureView(TextureAllocation * allocation, TextureViewKey key); - TextureView(WMT::Reference &&texture, uint64_t gpu_resource_id) : - texture(std::move(texture)), - gpu_resource_id(gpu_resource_id) {} - TextureView(const WMT::Reference &texture, uint64_t gpu_resource_id) : - texture(texture), - gpu_resource_id(gpu_resource_id) {} +private: + std::atomic refcount_ = {0u}; +}; + +class TextureViewRef : public Rc { +public: + using Rc::Rc; + + WMT::Texture + texture() const { + if (!*this) + return {}; + return ptr()->texture; + } + + Rc & + operator=(TextureView &ref) { + return (*this = &ref); + } }; class TextureAllocation : public Allocation { @@ -58,19 +89,19 @@ class TextureAllocation : public Allocation { return flags_; } + Rc descriptor; void *mappedMemory; uint64_t gpuResourceID; mach_port_t machPort; - DXMT_RESOURCE_RESIDENCY_STATE residencyState; EncoderDepKey depkey; private: TextureAllocation( - WMT::Reference &&buffer, void *mapped_buffer, const WMTTextureInfo &info, unsigned bytes_per_row, - Flags flags + Texture *descriptor, WMT::Reference &&buffer, void *mapped_buffer, const WMTTextureInfo &info, + unsigned bytes_per_row, Flags flags ); TextureAllocation( - WMT::Reference &&texture, const WMTTextureInfo &textureDescriptor, + Texture *descriptor, WMT::Reference &&texture, const WMTTextureInfo &textureDescriptor, Flags flags ); ~TextureAllocation(); @@ -82,10 +113,12 @@ class TextureAllocation : public Allocation { WMT::Reference buffer_; uint32_t version_ = 0; Flags flags_; - std::vector> cached_view_; + std::vector cached_view_; }; class Texture { + friend class TextureView; + public: void incRef(); void decRef(); @@ -168,18 +201,12 @@ class Texture { Rc allocate(Flags flags); Rc import(mach_port_t mach_port); - WMT::Texture view(TextureViewKey key); - WMT::Texture view(TextureViewKey key, TextureAllocation *allocation); - - TextureView const &view_(TextureViewKey key); - TextureView const &view_(TextureViewKey key, TextureAllocation *allocation); + TextureView &view(TextureViewKey key); + TextureView &view(TextureViewKey key, TextureAllocation *allocation); TextureViewKey checkViewUseArray(TextureViewKey key, bool isArray); TextureViewKey checkViewUseFormat(TextureViewKey key, WMTPixelFormat format); - DXMT_RESOURCE_RESIDENCY_STATE &residency(TextureViewKey key); - DXMT_RESOURCE_RESIDENCY_STATE &residency(TextureViewKey key, TextureAllocation *allocation); - Rc rename(Rc &&newAllocation); Texture(const WMTTextureInfo &info, WMT::Device device);