Refactor barrier usage & fix more validation errors.

This commit is contained in:
Skyth 2024-10-21 17:36:44 +03:00
parent 2e9d49f17d
commit 5578e84069
4 changed files with 71 additions and 72 deletions

View file

@ -1061,9 +1061,16 @@ namespace RT64 {
setSRV(descriptorIndex, nativeResource, &srvDesc); setSRV(descriptorIndex, nativeResource, &srvDesc);
} }
else { else if (nativeResource != nullptr) {
setSRV(descriptorIndex, nativeResource, nullptr); setSRV(descriptorIndex, nativeResource, nullptr);
} }
else {
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
setSRV(descriptorIndex, nullptr, &srvDesc);
}
break; break;
} }
@ -3341,7 +3348,6 @@ namespace RT64 {
# ifdef D3D12_DEBUG_LAYER_SUPRESS_SAMPLE_POSITIONS_ERROR # ifdef D3D12_DEBUG_LAYER_SUPRESS_SAMPLE_POSITIONS_ERROR
D3D12_MESSAGE_ID_SAMPLEPOSITIONS_MISMATCH_RECORDTIME_ASSUMEDFROMCLEAR, D3D12_MESSAGE_ID_SAMPLEPOSITIONS_MISMATCH_RECORDTIME_ASSUMEDFROMCLEAR,
D3D12_MESSAGE_ID_SAMPLEPOSITIONS_MISMATCH_DEFERRED, D3D12_MESSAGE_ID_SAMPLEPOSITIONS_MISMATCH_DEFERRED,
D3D12_MESSAGE_ID_RESOURCE_BARRIER_DUPLICATE_SUBRESOURCE_TRANSITIONS,
# endif # endif
}; };

View file

@ -2870,6 +2870,8 @@ namespace RT64 {
} }
void VulkanCommandList::copyTextureRegion(const RenderTextureCopyLocation &dstLocation, const RenderTextureCopyLocation &srcLocation, uint32_t dstX, uint32_t dstY, uint32_t dstZ, const RenderBox *srcBox) { void VulkanCommandList::copyTextureRegion(const RenderTextureCopyLocation &dstLocation, const RenderTextureCopyLocation &srcLocation, uint32_t dstX, uint32_t dstY, uint32_t dstZ, const RenderBox *srcBox) {
endActiveRenderPass();
assert(dstLocation.type != RenderTextureCopyType::UNKNOWN); assert(dstLocation.type != RenderTextureCopyType::UNKNOWN);
assert(srcLocation.type != RenderTextureCopyType::UNKNOWN); assert(srcLocation.type != RenderTextureCopyType::UNKNOWN);

View file

@ -292,13 +292,29 @@ static uint32_t g_quadCount;
static uint32_t g_mainThreadId; static uint32_t g_mainThreadId;
static ankerl::unordered_dense::map<RenderTexture*, RenderTextureLayout> g_barrierMap;
static void AddBarrier(GuestBaseTexture* texture, RenderTextureLayout layout)
{
if (texture != nullptr && texture->layout != layout)
{
g_barrierMap[texture->texture] = layout;
texture->layout = layout;
}
}
static std::vector<RenderTextureBarrier> g_barriers; static std::vector<RenderTextureBarrier> g_barriers;
static void FlushBarriers() static void FlushBarriers()
{ {
if (!g_barriers.empty()) if (!g_barrierMap.empty())
{ {
for (auto& [texture, layout] : g_barrierMap)
g_barriers.emplace_back(texture, layout);
g_commandLists[g_frame]->barriers(RenderBarrierStage::GRAPHICS | RenderBarrierStage::COPY, g_barriers); g_commandLists[g_frame]->barriers(RenderBarrierStage::GRAPHICS | RenderBarrierStage::COPY, g_barriers);
g_barrierMap.clear();
g_barriers.clear(); g_barriers.clear();
} }
} }
@ -721,7 +737,7 @@ static void BeginCommandList()
if (!g_swapChainValid) if (!g_swapChainValid)
g_backBuffer->texture = g_backBuffer->textureHolder.get(); g_backBuffer->texture = g_backBuffer->textureHolder.get();
g_backBuffer->pendingBarrier = true; g_backBuffer->layout = RenderTextureLayout::UNKNOWN;
auto& commandList = g_commandLists[g_frame]; auto& commandList = g_commandLists[g_frame];
@ -783,7 +799,7 @@ static void DestructResource(GuestResource* resource)
{ {
std::lock_guard lock(g_tempMutex); std::lock_guard lock(g_tempMutex);
g_tempTextures[g_frame].emplace_back(std::move(texture->texture)); g_tempTextures[g_frame].emplace_back(std::move(texture->textureHolder));
g_tempDescriptorIndices[g_frame].push_back(texture->descriptorIndex); g_tempDescriptorIndices[g_frame].push_back(texture->descriptorIndex);
} }
@ -862,7 +878,7 @@ static void UnlockTextureRect(GuestTexture* texture)
{ {
assert(GetCurrentThreadId() == g_mainThreadId); assert(GetCurrentThreadId() == g_mainThreadId);
g_barriers.emplace_back(texture->texture.get(), RenderTextureLayout::COPY_DEST); AddBarrier(texture, RenderTextureLayout::COPY_DEST);
FlushBarriers(); FlushBarriers();
uint32_t pitch = ComputeTexturePitch(texture); uint32_t pitch = ComputeTexturePitch(texture);
@ -872,10 +888,8 @@ static void UnlockTextureRect(GuestTexture* texture)
memcpy(allocation.memory, texture->mappedMemory, slicePitch); memcpy(allocation.memory, texture->mappedMemory, slicePitch);
g_commandLists[g_frame]->copyTextureRegion( g_commandLists[g_frame]->copyTextureRegion(
RenderTextureCopyLocation::Subresource(texture->texture.get(), 0), RenderTextureCopyLocation::Subresource(texture->texture, 0),
RenderTextureCopyLocation::PlacedFootprint(allocation.bufferReference.ref, texture->format, texture->width, texture->height, 1, pitch / RenderFormatSize(texture->format), allocation.bufferReference.offset)); RenderTextureCopyLocation::PlacedFootprint(allocation.bufferReference.ref, texture->format, texture->width, texture->height, 1, pitch / RenderFormatSize(texture->format), allocation.bufferReference.offset));
texture->pendingBarrier = true;
} }
static void* LockBuffer(GuestBuffer* buffer, uint32_t flags) static void* LockBuffer(GuestBuffer* buffer, uint32_t flags)
@ -978,7 +992,7 @@ static uint32_t HashVertexDeclaration(uint32_t vertexDeclaration)
static void Present() static void Present()
{ {
if (g_swapChainValid) if (g_swapChainValid)
g_barriers.emplace_back(g_backBuffer->texture, RenderTextureLayout::PRESENT); AddBarrier(g_backBuffer, RenderTextureLayout::PRESENT);
FlushBarriers(); FlushBarriers();
@ -1084,7 +1098,9 @@ static GuestTexture* CreateTexture(uint32_t width, uint32_t height, uint32_t dep
desc.arraySize = 1; desc.arraySize = 1;
desc.format = ConvertFormat(format); desc.format = ConvertFormat(format);
desc.flags = (desc.format == RenderFormat::D32_FLOAT) ? RenderTextureFlag::DEPTH_TARGET : RenderTextureFlag::NONE; desc.flags = (desc.format == RenderFormat::D32_FLOAT) ? RenderTextureFlag::DEPTH_TARGET : RenderTextureFlag::NONE;
texture->texture = g_device->createTexture(desc);
texture->textureHolder = g_device->createTexture(desc);
texture->texture = texture->textureHolder.get();
RenderTextureViewDesc viewDesc; RenderTextureViewDesc viewDesc;
viewDesc.format = desc.format; viewDesc.format = desc.format;
@ -1113,7 +1129,7 @@ static GuestTexture* CreateTexture(uint32_t width, uint32_t height, uint32_t dep
texture->format = desc.format; texture->format = desc.format;
texture->descriptorIndex = g_textureDescriptorAllocator.allocate(); texture->descriptorIndex = g_textureDescriptorAllocator.allocate();
g_textureDescriptorSet->setTexture(texture->descriptorIndex, texture->texture.get(), RenderTextureLayout::SHADER_READ, texture->textureView.get()); g_textureDescriptorSet->setTexture(texture->descriptorIndex, texture->texture, RenderTextureLayout::SHADER_READ, texture->textureView.get());
#ifdef _DEBUG #ifdef _DEBUG
texture->texture->setName(std::format("Texture {:X}", g_memory.MapVirtual(texture))); texture->texture->setName(std::format("Texture {:X}", g_memory.MapVirtual(texture)));
@ -1168,7 +1184,6 @@ static GuestSurface* CreateSurface(uint32_t width, uint32_t height, uint32_t for
surface->height = height; surface->height = height;
surface->format = desc.format; surface->format = desc.format;
surface->sampleCount = desc.multisampling.sampleCount; surface->sampleCount = desc.multisampling.sampleCount;
surface->pendingDiscard = true;
if (desc.multisampling.sampleCount != RenderSampleCount::COUNT_1 && desc.format == RenderFormat::D32_FLOAT) if (desc.multisampling.sampleCount != RenderSampleCount::COUNT_1 && desc.format == RenderFormat::D32_FLOAT)
{ {
@ -1267,8 +1282,8 @@ static void StretchRect(GuestDevice* device, uint32_t flags, uint32_t, GuestText
dstLayout = RenderTextureLayout::COPY_DEST; dstLayout = RenderTextureLayout::COPY_DEST;
} }
g_barriers.emplace_back(surface->texture, srcLayout); AddBarrier(surface, srcLayout);
g_barriers.emplace_back(texture->texture.get(), dstLayout); AddBarrier(texture, dstLayout);
FlushBarriers(); FlushBarriers();
auto& commandList = g_commandLists[g_frame]; auto& commandList = g_commandLists[g_frame];
@ -1297,7 +1312,7 @@ static void StretchRect(GuestDevice* device, uint32_t flags, uint32_t, GuestText
if (texture->framebuffer == nullptr) if (texture->framebuffer == nullptr)
{ {
RenderFramebufferDesc desc; RenderFramebufferDesc desc;
desc.depthAttachment = texture->texture.get(); desc.depthAttachment = texture->texture;
texture->framebuffer = g_device->createFramebuffer(desc); texture->framebuffer = g_device->createFramebuffer(desc);
} }
@ -1316,16 +1331,15 @@ static void StretchRect(GuestDevice* device, uint32_t flags, uint32_t, GuestText
} }
else else
{ {
commandList->resolveTexture(texture->texture.get(), surface->texture); commandList->resolveTexture(texture->texture, surface->texture);
} }
} }
else else
{ {
commandList->copyTexture(texture->texture.get(), surface->texture); commandList->copyTexture(texture->texture, surface->texture);
} }
surface->pendingBarrier = true; AddBarrier(texture, RenderTextureLayout::SHADER_READ);
texture->pendingBarrier = true;
} }
static void SetRenderTarget(GuestDevice* device, uint32_t index, GuestSurface* renderTarget) static void SetRenderTarget(GuestDevice* device, uint32_t index, GuestSurface* renderTarget)
@ -1350,32 +1364,10 @@ static void FlushFramebuffer()
{ {
auto& commandList = g_commandLists[g_frame]; auto& commandList = g_commandLists[g_frame];
if (g_renderTarget != nullptr && g_renderTarget->pendingBarrier) AddBarrier(g_renderTarget, RenderTextureLayout::COLOR_WRITE);
{ AddBarrier(g_depthStencil, RenderTextureLayout::DEPTH_WRITE);
g_barriers.emplace_back(g_renderTarget->texture, RenderTextureLayout::COLOR_WRITE);
g_renderTarget->pendingBarrier = false;
}
if (g_depthStencil != nullptr && g_depthStencil->pendingBarrier)
{
g_barriers.emplace_back(g_depthStencil->texture, RenderTextureLayout::DEPTH_WRITE);
g_depthStencil->pendingBarrier = false;
}
FlushBarriers(); FlushBarriers();
if (g_renderTarget != nullptr && g_renderTarget->pendingDiscard)
{
commandList->discardTexture(g_renderTarget->textureHolder.get());
g_renderTarget->pendingDiscard = false;
}
if (g_depthStencil != nullptr && g_depthStencil->pendingDiscard)
{
commandList->discardTexture(g_depthStencil->textureHolder.get());
g_depthStencil->pendingDiscard = false;
}
if (g_dirtyStates.renderTargetAndDepthStencil) if (g_dirtyStates.renderTargetAndDepthStencil)
{ {
GuestSurface* framebufferContainer = nullptr; GuestSurface* framebufferContainer = nullptr;
@ -1465,12 +1457,7 @@ static void GetViewport(GuestDevice* device, GuestViewport* viewport)
static void SetTexture(GuestDevice* device, uint32_t index, GuestTexture* texture) static void SetTexture(GuestDevice* device, uint32_t index, GuestTexture* texture)
{ {
if (texture != nullptr && texture->pendingBarrier) AddBarrier(texture, RenderTextureLayout::SHADER_READ);
{
g_barriers.emplace_back(texture->texture.get(), RenderTextureLayout::SHADER_READ);
texture->pendingBarrier = false;
}
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.textureIndices[index], texture != nullptr ? texture->descriptorIndex : NULL); SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.textureIndices[index], texture != nullptr ? texture->descriptorIndex : NULL);
} }
@ -2285,11 +2272,11 @@ static void D3DXFillVolumeTexture(GuestTexture* texture, uint32_t function, void
ExecuteCopyCommandList([&] ExecuteCopyCommandList([&]
{ {
g_copyCommandList->copyTextureRegion( g_copyCommandList->copyTextureRegion(
RenderTextureCopyLocation::Subresource(texture->texture.get(), 0), RenderTextureCopyLocation::Subresource(texture->texture, 0),
RenderTextureCopyLocation::PlacedFootprint(uploadBuffer.get(), texture->format, texture->width, texture->height, texture->depth, rowPitch0 / RenderFormatSize(texture->format), 0)); RenderTextureCopyLocation::PlacedFootprint(uploadBuffer.get(), texture->format, texture->width, texture->height, texture->depth, rowPitch0 / RenderFormatSize(texture->format), 0));
g_copyCommandList->copyTextureRegion( g_copyCommandList->copyTextureRegion(
RenderTextureCopyLocation::Subresource(texture->texture.get(), 1), RenderTextureCopyLocation::Subresource(texture->texture, 1),
RenderTextureCopyLocation::PlacedFootprint(uploadBuffer.get(), texture->format, texture->width / 2, texture->height / 2, texture->depth / 2, rowPitch1 / RenderFormatSize(texture->format), slicePitch0)); RenderTextureCopyLocation::PlacedFootprint(uploadBuffer.get(), texture->format, texture->width / 2, texture->height / 2, texture->depth / 2, rowPitch1 / RenderFormatSize(texture->format), slicePitch0));
}); });
} }
@ -2514,7 +2501,11 @@ static void MakePictureData(GuestPictureData* pictureData, uint8_t* data, uint32
desc.arraySize = ddsDesc.type == ddspp::TextureType::Cubemap ? ddsDesc.arraySize * 6 : ddsDesc.arraySize; desc.arraySize = ddsDesc.type == ddspp::TextureType::Cubemap ? ddsDesc.arraySize * 6 : ddsDesc.arraySize;
desc.format = ConvertDXGIFormat(ddsDesc.format); desc.format = ConvertDXGIFormat(ddsDesc.format);
desc.flags = ddsDesc.type == ddspp::TextureType::Cubemap ? RenderTextureFlag::CUBE : RenderTextureFlag::NONE; desc.flags = ddsDesc.type == ddspp::TextureType::Cubemap ? RenderTextureFlag::CUBE : RenderTextureFlag::NONE;
texture->texture = g_device->createTexture(desc);
texture->textureHolder = g_device->createTexture(desc);
texture->texture = texture->textureHolder.get();
texture->layout = RenderTextureLayout::COPY_DEST;
#ifdef _DEBUG #ifdef _DEBUG
texture->texture->setName(reinterpret_cast<char*>(g_memory.Translate(pictureData->name + 2))); texture->texture->setName(reinterpret_cast<char*>(g_memory.Translate(pictureData->name + 2)));
#endif #endif
@ -2525,7 +2516,7 @@ static void MakePictureData(GuestPictureData* pictureData, uint8_t* data, uint32
viewDesc.mipLevels = ddsDesc.numMips; viewDesc.mipLevels = ddsDesc.numMips;
texture->textureView = texture->texture->createTextureView(viewDesc); texture->textureView = texture->texture->createTextureView(viewDesc);
texture->descriptorIndex = g_textureDescriptorAllocator.allocate(); texture->descriptorIndex = g_textureDescriptorAllocator.allocate();
g_textureDescriptorSet->setTexture(texture->descriptorIndex, texture->texture.get(), RenderTextureLayout::SHADER_READ, texture->textureView.get()); g_textureDescriptorSet->setTexture(texture->descriptorIndex, texture->texture, RenderTextureLayout::SHADER_READ, texture->textureView.get());
struct Slice struct Slice
{ {
@ -2591,14 +2582,14 @@ static void MakePictureData(GuestPictureData* pictureData, uint8_t* data, uint32
ExecuteCopyCommandList([&] ExecuteCopyCommandList([&]
{ {
g_copyCommandList->barriers(RenderBarrierStage::COPY, RenderTextureBarrier(texture->texture.get(), RenderTextureLayout::COPY_DEST)); g_copyCommandList->barriers(RenderBarrierStage::COPY, RenderTextureBarrier(texture->texture, RenderTextureLayout::COPY_DEST));
for (size_t i = 0; i < slices.size(); i++) for (size_t i = 0; i < slices.size(); i++)
{ {
auto& slice = slices[i]; auto& slice = slices[i];
g_copyCommandList->copyTextureRegion( g_copyCommandList->copyTextureRegion(
RenderTextureCopyLocation::Subresource(texture->texture.get(), i), RenderTextureCopyLocation::Subresource(texture->texture, i),
RenderTextureCopyLocation::PlacedFootprint(uploadBuffer.get(), desc.format, slice.width, slice.height, slice.depth, (slice.dstRowPitch * 8) / ddsDesc.bitsPerPixelOrBlock * ddsDesc.blockWidth, slice.dstOffset)); RenderTextureCopyLocation::PlacedFootprint(uploadBuffer.get(), desc.format, slice.width, slice.height, slice.depth, (slice.dstRowPitch * 8) / ddsDesc.bitsPerPixelOrBlock * ddsDesc.blockWidth, slice.dstOffset));
} }
}); });

View file

@ -86,18 +86,27 @@ enum GuestFormat
D3DFMT_UNKNOWN = 0xFFFFFFFF D3DFMT_UNKNOWN = 0xFFFFFFFF
}; };
// Texture/VolumeTexture struct GuestBaseTexture : GuestResource
struct GuestTexture : GuestResource
{ {
std::unique_ptr<RenderTexture> texture; std::unique_ptr<RenderTexture> textureHolder;
RenderTexture* texture = nullptr;
std::unique_ptr<RenderTextureView> textureView; std::unique_ptr<RenderTextureView> textureView;
uint32_t width = 0; uint32_t width = 0;
uint32_t height = 0; uint32_t height = 0;
uint32_t depth = 0;
RenderFormat format = RenderFormat::UNKNOWN; RenderFormat format = RenderFormat::UNKNOWN;
void* mappedMemory = nullptr;
uint32_t descriptorIndex = 0; uint32_t descriptorIndex = 0;
bool pendingBarrier = true; RenderTextureLayout layout = RenderTextureLayout::UNKNOWN;
GuestBaseTexture(ResourceType type) : GuestResource(type)
{
}
};
// Texture/VolumeTexture
struct GuestTexture : GuestBaseTexture
{
uint32_t depth = 0;
void* mappedMemory = nullptr;
std::unique_ptr<RenderFramebuffer> framebuffer; std::unique_ptr<RenderFramebuffer> framebuffer;
}; };
@ -141,19 +150,10 @@ struct GuestSurfaceDesc
}; };
// RenderTarget/DepthStencil // RenderTarget/DepthStencil
struct GuestSurface : GuestResource struct GuestSurface : GuestBaseTexture
{ {
std::unique_ptr<RenderTexture> textureHolder;
RenderTexture* texture = nullptr;
std::unique_ptr<RenderTextureView> textureView;
uint32_t width = 0;
uint32_t height = 0;
RenderFormat format = RenderFormat::UNKNOWN;
ankerl::unordered_dense::map<const RenderTexture*, std::unique_ptr<RenderFramebuffer>> framebuffers; ankerl::unordered_dense::map<const RenderTexture*, std::unique_ptr<RenderFramebuffer>> framebuffers;
RenderSampleCounts sampleCount = RenderSampleCount::COUNT_1; RenderSampleCounts sampleCount = RenderSampleCount::COUNT_1;
uint32_t descriptorIndex = 0;
bool pendingBarrier = true;
bool pendingDiscard = false;
}; };
enum GuestDeclType enum GuestDeclType