fix vulkan error from astrobot (#689)

* fix vulkan error from astrobot

* a bit of a clean

* a bit of a clean
This commit is contained in:
Astell
2026-07-30 11:58:43 +02:00
committed by GitHub
parent f08308daf2
commit 5f1bd5a77c
@@ -9271,6 +9271,27 @@ internal static unsafe class VulkanVideoPresenter
!_guestImages.ContainsKey(texture.Address)) !_guestImages.ContainsKey(texture.Address))
{ {
var guestFormat = GetGuestTextureFormat(texture.Format, texture.NumberType); var guestFormat = GetGuestTextureFormat(texture.Format, texture.NumberType);
var canonicalView = view;
if (texture.DstSelect != 0xFAC)
{
var identityViewInfo = new ImageViewCreateInfo
{
SType = StructureType.ImageViewCreateInfo,
Image = image,
ViewType = GetGuestTextureViewType(
texture.Type,
texture.ArrayedView),
Format = vkFormat,
Components = ToVkComponentMapping(0xFAC),
SubresourceRange = ColorSubresourceRange(layerCount: layers),
};
Check(
_vk.CreateImageView(_device, &identityViewInfo, null, out canonicalView),
"vkCreateImageView(texture identity)");
SetDebugName(ObjectType.ImageView, canonicalView.Handle, $"{debugName} identity view");
}
var guestImage = new GuestImageResource var guestImage = new GuestImageResource
{ {
Address = texture.Address, Address = texture.Address,
@@ -9286,7 +9307,7 @@ internal static unsafe class VulkanVideoPresenter
Format = vkFormat, Format = vkFormat,
Image = image, Image = image,
Memory = imageMemory, Memory = imageMemory,
View = view, View = canonicalView,
InitialUploadPending = true, InitialUploadPending = true,
IsCpuBacked = true, IsCpuBacked = true,
CpuContentFingerprint = contentFingerprint, CpuContentFingerprint = contentFingerprint,
@@ -11186,6 +11207,8 @@ internal static unsafe class VulkanVideoPresenter
EnsureGuestSubmissionCapacity(); EnsureGuestSubmissionCapacity();
resources = CreateComputeDispatchResources(work); resources = CreateComputeDispatchResources(work);
FlushBatchedGuestCommands();
var batchCount = Math.Max( var batchCount = Math.Max(
1u, 1u,
(uint)Math.Ceiling(work.GroupCountZ / (double)MaxComputeZSlicesPerSubmission)); (uint)Math.Ceiling(work.GroupCountZ / (double)MaxComputeZSlicesPerSubmission));
@@ -14338,11 +14361,6 @@ internal static unsafe class VulkanVideoPresenter
pendingGuestWork.Queue.Name, pendingGuestWork.Queue.Name,
StringComparison.Ordinal)) StringComparison.Ordinal))
{ {
// A host command buffer must never contain commands from
// two independent guest queues: an ordered action fences
// only its own queue's predecessor submissions.
// Keep the previous work label so a device-lost on this
// flush still names the draws that filled the batch.
FlushBatchedGuestCommands(); FlushBatchedGuestCommands();
} }
@@ -14382,14 +14400,7 @@ internal static unsafe class VulkanVideoPresenter
} }
try try
{ {
// A host-decoded movie only overrides which image gets
// presented (see the presentation selection below); the
// guest's own command stream keeps draining normally.
// Silently discarding these instead of executing them
// leaves guest-visible completion state (labels, buffers,
// job results) permanently unwritten, which desyncs the
// engine's own job system and previously crashed it
// shortly after the movie finished.
switch (work) switch (work)
{ {
case VulkanOffscreenGuestDraw offscreenDraw: case VulkanOffscreenGuestDraw offscreenDraw:
@@ -14711,6 +14722,8 @@ internal static unsafe class VulkanVideoPresenter
$"[LOADER][ERROR] Vulkan VideoOut translated draw setup failed: {exception.Message}"); $"[LOADER][ERROR] Vulkan VideoOut translated draw setup failed: {exception.Message}");
return; return;
} }
FlushBatchedGuestCommands();
} }
uint imageIndex; uint imageIndex;
@@ -15322,6 +15335,11 @@ internal static unsafe class VulkanVideoPresenter
RecordGuestDepthForSampling(depth, shaderStage); RecordGuestDepthForSampling(depth, shaderStage);
} }
if (!texture.IsStorage && texture.GuestImage is { } sampledGuestImage)
{
RecordGuestImageForSampling(sampledGuestImage, shaderStage);
}
if (!texture.NeedsUpload) if (!texture.NeedsUpload)
{ {
continue; continue;
@@ -15529,6 +15547,76 @@ internal static unsafe class VulkanVideoPresenter
depth.Layout = ImageLayout.ShaderReadOnlyOptimal; depth.Layout = ImageLayout.ShaderReadOnlyOptimal;
} }
private void RecordGuestImageForSampling(
GuestImageResource guestImage,
PipelineStageFlags shaderStage)
{
if (guestImage.Initialized || guestImage.InitialUploadPending)
{
return;
}
var range = ColorSubresourceRange(0, Math.Max(guestImage.MipLevels, 1));
var toTransfer = new ImageMemoryBarrier
{
SType = StructureType.ImageMemoryBarrier,
DstAccessMask = AccessFlags.TransferWriteBit,
OldLayout = ImageLayout.Undefined,
NewLayout = ImageLayout.TransferDstOptimal,
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
Image = guestImage.Image,
SubresourceRange = range,
};
_vk.CmdPipelineBarrier(
_commandBuffer,
PipelineStageFlags.TopOfPipeBit,
PipelineStageFlags.TransferBit,
0,
0,
null,
0,
null,
1,
&toTransfer);
var clearValue = new ClearColorValue(0f, 0f, 0f, 0f);
_vk.CmdClearColorImage(
_commandBuffer,
guestImage.Image,
ImageLayout.TransferDstOptimal,
&clearValue,
1,
&range);
var toShaderRead = new ImageMemoryBarrier
{
SType = StructureType.ImageMemoryBarrier,
SrcAccessMask = AccessFlags.TransferWriteBit,
DstAccessMask = AccessFlags.ShaderReadBit,
OldLayout = ImageLayout.TransferDstOptimal,
NewLayout = ImageLayout.ShaderReadOnlyOptimal,
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
Image = guestImage.Image,
SubresourceRange = range,
};
_vk.CmdPipelineBarrier(
_commandBuffer,
PipelineStageFlags.TransferBit,
shaderStage,
0,
0,
null,
0,
null,
1,
&toShaderRead);
guestImage.Initialized = true;
}
private void RecordStandaloneGuestDepthClear(GuestDepthResource depth) private void RecordStandaloneGuestDepthClear(GuestDepthResource depth)
{ {
var depthRange = new ImageSubresourceRange( var depthRange = new ImageSubresourceRange(