Fix Cool Edge whale not having reflections. (#1441)
Some checks are pending
validate-internal / build (push) Waiting to run

* Fix Cool Edge whale not having reflections.

* Fix Vulkan validation error.
This commit is contained in:
Skyth (Asilkan) 2025-03-23 18:59:10 +03:00 committed by GitHub
parent 41fd1761b1
commit a02f34b028
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 59 additions and 13 deletions

View file

@ -683,6 +683,9 @@ static void DestructTempResources()
if (texture->patchedTexture != nullptr) if (texture->patchedTexture != nullptr)
g_textureDescriptorAllocator.free(texture->patchedTexture->descriptorIndex); g_textureDescriptorAllocator.free(texture->patchedTexture->descriptorIndex);
if (texture->recreatedCubeMapTexture != nullptr)
g_textureDescriptorAllocator.free(texture->recreatedCubeMapTexture->descriptorIndex);
texture->~GuestTexture(); texture->~GuestTexture();
break; break;
} }
@ -3647,6 +3650,14 @@ static void SetTextureInRenderThread(uint32_t index, GuestTexture* texture)
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.texture3DIndices[index], texture != nullptr && SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.texture3DIndices[index], texture != nullptr &&
viewDimension == RenderTextureViewDimension::TEXTURE_3D ? texture->descriptorIndex : TEXTURE_DESCRIPTOR_NULL_TEXTURE_3D); viewDimension == RenderTextureViewDimension::TEXTURE_3D ? texture->descriptorIndex : TEXTURE_DESCRIPTOR_NULL_TEXTURE_3D);
// Check if there's a cubemap texture we recreated and assign it if it's valid. The shader will pick whichever is correct.
if (viewDimension == RenderTextureViewDimension::TEXTURE_2D && texture->recreatedCubeMapTexture != nullptr)
{
texture = texture->recreatedCubeMapTexture.get();
AddBarrier(texture, RenderTextureLayout::SHADER_READ);
viewDimension = texture->viewDimension;
}
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.textureCubeIndices[index], texture != nullptr && SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.textureCubeIndices[index], texture != nullptr &&
viewDimension == RenderTextureViewDimension::TEXTURE_CUBE ? texture->descriptorIndex : TEXTURE_DESCRIPTOR_NULL_TEXTURE_CUBE); viewDimension == RenderTextureViewDimension::TEXTURE_CUBE ? texture->descriptorIndex : TEXTURE_DESCRIPTOR_NULL_TEXTURE_CUBE);
} }
@ -5477,21 +5488,30 @@ static RenderFormat ConvertDXGIFormat(ddspp::DXGIFormat format)
} }
} }
static bool LoadTexture(GuestTexture& texture, const uint8_t* data, size_t dataSize, RenderComponentMapping componentMapping) static bool LoadTexture(GuestTexture& texture, const uint8_t* data, size_t dataSize, RenderComponentMapping componentMapping, bool forceCubeMap = false)
{ {
ddspp::Descriptor ddsDesc; ddspp::Descriptor ddsDesc;
if (ddspp::decode_header((unsigned char *)(data), ddsDesc) != ddspp::Error) if (ddspp::decode_header((unsigned char *)(data), ddsDesc) != ddspp::Error)
{ {
forceCubeMap &= (ddsDesc.type == ddspp::Texture2D) && (ddsDesc.arraySize == 1);
uint32_t arraySize = ddsDesc.type == ddspp::TextureType::Cubemap ? (ddsDesc.arraySize * 6) : ddsDesc.arraySize;
RenderTextureDesc desc; RenderTextureDesc desc;
desc.dimension = ConvertTextureDimension(ddsDesc.type); desc.dimension = ConvertTextureDimension(ddsDesc.type);
desc.width = ddsDesc.width; desc.width = ddsDesc.width;
desc.height = ddsDesc.height; desc.height = ddsDesc.height;
desc.depth = ddsDesc.depth; desc.depth = ddsDesc.depth;
desc.mipLevels = ddsDesc.numMips; desc.mipLevels = ddsDesc.numMips;
desc.arraySize = ddsDesc.type == ddspp::TextureType::Cubemap ? ddsDesc.arraySize * 6 : ddsDesc.arraySize; desc.arraySize = 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;
if (forceCubeMap)
{
desc.arraySize = 6;
desc.flags = RenderTextureFlag::CUBE;
}
texture.textureHolder = g_device->createTexture(desc); texture.textureHolder = g_device->createTexture(desc);
texture.texture = texture.textureHolder.get(); texture.texture = texture.textureHolder.get();
texture.layout = RenderTextureLayout::COPY_DEST; texture.layout = RenderTextureLayout::COPY_DEST;
@ -5501,6 +5521,10 @@ static bool LoadTexture(GuestTexture& texture, const uint8_t* data, size_t dataS
viewDesc.dimension = ConvertTextureViewDimension(ddsDesc.type); viewDesc.dimension = ConvertTextureViewDimension(ddsDesc.type);
viewDesc.mipLevels = ddsDesc.numMips; viewDesc.mipLevels = ddsDesc.numMips;
viewDesc.componentMapping = componentMapping; viewDesc.componentMapping = componentMapping;
if (forceCubeMap)
viewDesc.dimension = RenderTextureViewDimension::TEXTURE_CUBE;
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, RenderTextureLayout::SHADER_READ, texture.textureView.get()); g_textureDescriptorSet->setTexture(texture.descriptorIndex, texture.texture, RenderTextureLayout::SHADER_READ, texture.textureView.get());
@ -5525,7 +5549,7 @@ static bool LoadTexture(GuestTexture& texture, const uint8_t* data, size_t dataS
uint32_t curSrcOffset = 0; uint32_t curSrcOffset = 0;
uint32_t curDstOffset = 0; uint32_t curDstOffset = 0;
for (uint32_t arraySlice = 0; arraySlice < desc.arraySize; arraySlice++) for (uint32_t arraySlice = 0; arraySlice < arraySize; arraySlice++)
{ {
for (uint32_t mipSlice = 0; mipSlice < ddsDesc.numMips; mipSlice++) for (uint32_t mipSlice = 0; mipSlice < ddsDesc.numMips; mipSlice++)
{ {
@ -5575,13 +5599,24 @@ static bool LoadTexture(GuestTexture& texture, const uint8_t* data, size_t dataS
{ {
g_copyCommandList->barriers(RenderBarrierStage::COPY, RenderTextureBarrier(texture.texture, RenderTextureLayout::COPY_DEST)); g_copyCommandList->barriers(RenderBarrierStage::COPY, RenderTextureBarrier(texture.texture, RenderTextureLayout::COPY_DEST));
for (size_t i = 0; i < slices.size(); i++) auto copyTextureRegion = [&](Slice& slice, uint32_t subresourceIndex)
{ {
auto& slice = slices[i]; g_copyCommandList->copyTextureRegion(
RenderTextureCopyLocation::Subresource(texture.texture, subresourceIndex),
RenderTextureCopyLocation::PlacedFootprint(uploadBuffer.get(), desc.format, slice.width, slice.height, slice.depth, (slice.dstRowPitch * 8) / ddsDesc.bitsPerPixelOrBlock * ddsDesc.blockWidth, slice.dstOffset));
};
g_copyCommandList->copyTextureRegion( for (size_t i = 0; i < slices.size(); i++)
RenderTextureCopyLocation::Subresource(texture.texture, i), copyTextureRegion(slices[i], i);
RenderTextureCopyLocation::PlacedFootprint(uploadBuffer.get(), desc.format, slice.width, slice.height, slice.depth, (slice.dstRowPitch * 8) / ddsDesc.bitsPerPixelOrBlock * ddsDesc.blockWidth, slice.dstOffset));
// Duplicate the first face across the remaining 6 faces.
if (forceCubeMap)
{
for (size_t i = 1; i < 6; i++)
{
for (size_t j = 0; j < slices.size(); j++)
copyTextureRegion(slices[j], (slices.size() * i) + j);
}
} }
}); });
@ -5654,13 +5689,12 @@ std::unique_ptr<GuestTexture> LoadTexture(const uint8_t* data, size_t dataSize,
return nullptr; return nullptr;
} }
static void DiffPatchTexture(GuestTexture& texture, uint8_t* data, uint32_t dataSize) static void DiffPatchTexture(GuestTexture& texture, uint8_t* data, uint32_t dataSize, XXH64_hash_t hash)
{ {
auto header = reinterpret_cast<BlockCompressionDiffPatchHeader*>(g_buttonBcDiff.get()); auto header = reinterpret_cast<BlockCompressionDiffPatchHeader*>(g_buttonBcDiff.get());
auto entries = reinterpret_cast<BlockCompressionDiffPatchEntry*>(g_buttonBcDiff.get() + header->entriesOffset); auto entries = reinterpret_cast<BlockCompressionDiffPatchEntry*>(g_buttonBcDiff.get() + header->entriesOffset);
auto end = entries + header->entryCount; auto end = entries + header->entryCount;
XXH64_hash_t hash = XXH3_64bits(data, dataSize);
auto findResult = std::lower_bound(entries, end, hash, [](BlockCompressionDiffPatchEntry& lhs, XXH64_hash_t rhs) auto findResult = std::lower_bound(entries, end, hash, [](BlockCompressionDiffPatchEntry& lhs, XXH64_hash_t rhs)
{ {
return lhs.hash < rhs; return lhs.hash < rhs;
@ -5693,8 +5727,19 @@ static void MakePictureData(GuestPictureData* pictureData, uint8_t* data, uint32
#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
XXH64_hash_t hash = XXH3_64bits(data, dataSize);
DiffPatchTexture(texture, data, dataSize); // The whale in Cool Edge has a 2D texture assigned as a cubemap which makes it not display in recomp.
// The hardware duplicates the first face to the remaining 6 faces, so to simulate that we'll recreate the asset.
bool forceCubeMap = (dataSize == 0xAB38) && (hash == 0x160E9E250FDE88A9);
if (forceCubeMap)
{
GuestTexture recreatedCubeMapTexture(ResourceType::Texture);
if (LoadTexture(recreatedCubeMapTexture, data, dataSize, {}, true))
texture.recreatedCubeMapTexture = std::make_unique<GuestTexture>(std::move(recreatedCubeMapTexture));
}
DiffPatchTexture(texture, data, dataSize, hash);
pictureData->texture = g_memory.MapVirtual(g_userHeap.AllocPhysical<GuestTexture>(std::move(texture))); pictureData->texture = g_memory.MapVirtual(g_userHeap.AllocPhysical<GuestTexture>(std::move(texture)));
pictureData->type = 0; pictureData->type = 0;

View file

@ -158,6 +158,7 @@ struct GuestTexture : GuestBaseTexture
void* mappedMemory = nullptr; void* mappedMemory = nullptr;
std::unique_ptr<RenderFramebuffer> framebuffer; std::unique_ptr<RenderFramebuffer> framebuffer;
std::unique_ptr<GuestTexture> patchedTexture; std::unique_ptr<GuestTexture> patchedTexture;
std::unique_ptr<GuestTexture> recreatedCubeMapTexture;
struct GuestSurface* sourceSurface = nullptr; struct GuestSurface* sourceSurface = nullptr;
}; };