Implement movie rendering & fix some validation errors.

This commit is contained in:
Skyth
2024-10-20 18:47:26 +03:00
parent 4ee432d759
commit 66c20e73c9
15 changed files with 458 additions and 139 deletions
+135 -28
View File
@@ -13,6 +13,10 @@
#include "shader/copy_vs.hlsl.dxil.h"
#include "shader/copy_vs.hlsl.spirv.h"
#include "shader/movie_vs.hlsl.dxil.h"
#include "shader/movie_vs.hlsl.spirv.h"
#include "shader/movie_ps.hlsl.dxil.h"
#include "shader/movie_ps.hlsl.spirv.h"
#include "shader/resolve_msaa_depth_2x.hlsl.dxil.h"
#include "shader/resolve_msaa_depth_2x.hlsl.spirv.h"
#include "shader/resolve_msaa_depth_4x.hlsl.dxil.h"
@@ -280,6 +284,8 @@ static std::vector<uint32_t> g_tempDescriptorIndices[NUM_FRAMES];
static RenderBufferReference g_quadIndexBuffer;
static uint32_t g_quadCount;
static uint32_t g_mainThreadId;
static std::vector<RenderTextureBarrier> g_barriers;
static void FlushBarriers()
@@ -519,6 +525,13 @@ static const std::pair<GuestRenderState, void*> g_setRenderStateFunctions[] =
static std::unique_ptr<RenderPipeline> g_resolveMsaaDepthPipelines[3];
#define CREATE_SHADER(NAME) \
g_device->createShader( \
g_vulkan ? g_##NAME##_spirv : g_##NAME##_dxil, \
g_vulkan ? sizeof(g_##NAME##_spirv) : sizeof(g_##NAME##_dxil), \
"main", \
g_vulkan ? RenderShaderFormat::SPIRV : RenderShaderFormat::DXIL)
static void CreateHostDevice()
{
for (uint32_t i = 0; i < 16; i++)
@@ -550,6 +563,8 @@ static void CreateHostDevice()
for (auto& renderSemaphore : g_renderSemaphores)
renderSemaphore = g_device->createCommandSemaphore();
g_mainThreadId = GetCurrentThreadId();
RenderPipelineLayoutBuilder pipelineLayoutBuilder;
pipelineLayoutBuilder.begin(false, true);
@@ -562,6 +577,8 @@ static void CreateHostDevice()
descriptorSetBuilder.end(true, TEXTURE_DESCRIPTOR_SIZE);
g_textureDescriptorSet = descriptorSetBuilder.create(g_device.get());
g_textureDescriptorSet->setTexture(0, nullptr, RenderTextureLayout::SHADER_READ);
pipelineLayoutBuilder.addDescriptorSet(descriptorSetBuilder);
pipelineLayoutBuilder.addDescriptorSet(descriptorSetBuilder);
pipelineLayoutBuilder.addDescriptorSet(descriptorSetBuilder);
@@ -571,6 +588,11 @@ static void CreateHostDevice()
descriptorSetBuilder.end(true, SAMPLER_DESCRIPTOR_SIZE);
g_samplerDescriptorSet = descriptorSetBuilder.create(g_device.get());
auto& [descriptorIndex, sampler] = g_samplerStates[XXH3_64bits(&g_samplerDescs[0], sizeof(RenderSamplerDesc))];
descriptorIndex = 1;
sampler = g_device->createSampler(g_samplerDescs[0]);
g_samplerDescriptorSet->setSampler(0, sampler.get());
pipelineLayoutBuilder.addDescriptorSet(descriptorSetBuilder);
if (g_vulkan)
@@ -588,13 +610,6 @@ static void CreateHostDevice()
g_pipelineLayout = pipelineLayoutBuilder.create(g_device.get());
#define CREATE_SHADER(NAME) \
g_device->createShader( \
g_vulkan ? g_##NAME##_spirv : g_##NAME##_dxil, \
g_vulkan ? sizeof(g_##NAME##_spirv) : sizeof(g_##NAME##_dxil), \
"main", \
g_vulkan ? RenderShaderFormat::SPIRV : RenderShaderFormat::DXIL)
auto copyShader = CREATE_SHADER(copy_vs);
for (size_t i = 0; i < std::size(g_resolveMsaaDepthPipelines); i++)
@@ -623,8 +638,6 @@ static void CreateHostDevice()
desc.depthTargetFormat = RenderFormat::D32_FLOAT;
g_resolveMsaaDepthPipelines[i] = g_device->createGraphicsPipeline(desc);
}
#undef CREATE_SHADER
}
static void WaitForGPU()
@@ -819,31 +832,41 @@ static void DestructResource(GuestResource* resource)
static constexpr uint32_t PITCH_ALIGNMENT = 0x100;
static constexpr uint32_t PLACEMENT_ALIGNMENT = 0x200;
static uint32_t ComputeTexturePitch(GuestTexture* texture)
{
return (texture->width * RenderFormatSize(texture->format) + PITCH_ALIGNMENT - 1) & ~(PITCH_ALIGNMENT - 1);
}
static void LockTextureRect(GuestTexture* texture, uint32_t, GuestLockedRect* lockedRect)
{
uint32_t pitch = (texture->width * RenderFormatSize(texture->format) + PITCH_ALIGNMENT - 1) & ~(PITCH_ALIGNMENT - 1);
uint32_t pitch = ComputeTexturePitch(texture);
uint32_t slicePitch = pitch * texture->height;
if (texture->mappedMemory == nullptr)
texture->mappedMemory = g_userHeap.AllocPhysical(pitch * texture->height, 0x10);
texture->mappedMemory = g_userHeap.AllocPhysical(slicePitch, 0x10);
lockedRect->pitch = pitch;
lockedRect->bits = g_memory.MapVirtual(texture->mappedMemory);
}
template<typename T>
static void ExecuteCopyCommandList(const T& function)
{
std::lock_guard lock(g_copyMutex);
g_copyCommandList->begin();
function();
g_copyCommandList->end();
g_copyQueue->executeCommandLists(g_copyCommandList.get(), g_copyCommandFence.get());
g_copyQueue->waitForCommandFence(g_copyCommandFence.get());
}
static void UnlockTextureRect(GuestTexture* texture)
{
assert(GetCurrentThreadId() == g_mainThreadId);
g_barriers.emplace_back(texture->texture.get(), RenderTextureLayout::COPY_DEST);
FlushBarriers();
uint32_t pitch = ComputeTexturePitch(texture);
uint32_t slicePitch = pitch * texture->height;
auto allocation = g_uploadAllocators[g_frame].allocate(slicePitch, PLACEMENT_ALIGNMENT);
memcpy(allocation.memory, texture->mappedMemory, slicePitch);
g_commandLists[g_frame]->copyTextureRegion(
RenderTextureCopyLocation::Subresource(texture->texture.get(), 0),
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)
@@ -861,6 +884,18 @@ static void* LockVertexBuffer(GuestBuffer* buffer, uint32_t, uint32_t, uint32_t
return LockBuffer(buffer, flags);
}
template<typename T>
static void ExecuteCopyCommandList(const T& function)
{
std::lock_guard lock(g_copyMutex);
g_copyCommandList->begin();
function();
g_copyCommandList->end();
g_copyQueue->executeCommandLists(g_copyCommandList.get(), g_copyCommandFence.get());
g_copyQueue->waitForCommandFence(g_copyCommandFence.get());
}
template<typename T>
static void UnlockBuffer(GuestBuffer* buffer)
{
@@ -1046,6 +1081,21 @@ static GuestTexture* CreateTexture(uint32_t width, uint32_t height, uint32_t dep
viewDesc.format = desc.format;
viewDesc.dimension = texture->type == ResourceType::VolumeTexture ? RenderTextureViewDimension::TEXTURE_3D : RenderTextureViewDimension::TEXTURE_2D;
viewDesc.mipLevels = levels;
switch (format)
{
case D3DFMT_D24FS8:
case D3DFMT_D24S8:
case D3DFMT_L8:
case D3DFMT_L8_2:
viewDesc.componentMapping = RenderComponentMapping(RenderSwizzle::R, RenderSwizzle::R, RenderSwizzle::R, RenderSwizzle::ONE);
break;
case D3DFMT_X8R8G8B8:
viewDesc.componentMapping = RenderComponentMapping(RenderSwizzle::G, RenderSwizzle::B, RenderSwizzle::A, RenderSwizzle::ONE);
break;
}
texture->textureView = texture->texture->createTextureView(viewDesc);
texture->width = width;
@@ -1056,6 +1106,10 @@ static GuestTexture* CreateTexture(uint32_t width, uint32_t height, uint32_t dep
g_textureDescriptorSet->setTexture(texture->descriptorIndex, texture->texture.get(), RenderTextureLayout::SHADER_READ, texture->textureView.get());
#ifdef _DEBUG
texture->texture->setName(std::format("Texture {:X}", g_memory.MapVirtual(texture)));
#endif
return texture;
}
@@ -1118,6 +1172,10 @@ static GuestSurface* CreateSurface(uint32_t width, uint32_t height, uint32_t for
g_textureDescriptorSet->setTexture(surface->descriptorIndex, surface->textureHolder.get(), RenderTextureLayout::SHADER_READ, surface->textureView.get());
}
#ifdef _DEBUG
surface->texture->setName(std::format("{} {:X}", desc.flags & RenderTextureFlag::RENDER_TARGET ? "Render Target" : "Depth Stencil", g_memory.MapVirtual(surface)));
#endif
return surface;
}
@@ -1588,10 +1646,10 @@ static void FlushRenderState(GuestDevice* device)
descriptorIndex = g_samplerStates.size();
sampler = g_device->createSampler(samplerDesc);
g_samplerDescriptorSet->setSampler(descriptorIndex, sampler.get());
g_samplerDescriptorSet->setSampler(descriptorIndex - 1, sampler.get());
}
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.samplerIndices[i], descriptorIndex);
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.samplerIndices[i], descriptorIndex - 1);
}
device->dirtyFlags[3] = device->dirtyFlags[3].get() & ~mask;
@@ -2337,6 +2395,8 @@ static RenderFormat ConvertDXGIFormat(ddspp::DXGIFormat format)
return RenderFormat::R8G8B8A8_SINT;
case ddspp::B8G8R8A8_UNORM:
return RenderFormat::B8G8R8A8_UNORM;
case ddspp::B8G8R8X8_UNORM:
return RenderFormat::B8G8R8A8_UNORM;
case ddspp::R16G16_TYPELESS:
return RenderFormat::R16G16_TYPELESS;
case ddspp::R16G16_FLOAT:
@@ -2567,7 +2627,8 @@ void IndexBufferLengthMidAsmHook(PPCRegister& r3)
void SetShadowResolutionMidAsmHook(PPCRegister& r11)
{
r11.u64 = 4096;
if (Config::ShadowResolution > 0)
r11.u64 = Config::ShadowResolution;
}
void Primitive2DHalfPixelOffsetMidAsmHook(PPCRegister& f13)
@@ -2577,8 +2638,8 @@ void Primitive2DHalfPixelOffsetMidAsmHook(PPCRegister& f13)
static void SetResolution(be<uint32_t>* device)
{
uint32_t width = g_swapChain->getWidth();
uint32_t height = g_swapChain->getHeight();
uint32_t width = uint32_t(g_swapChain->getWidth() * Config::ResolutionScale);
uint32_t height = uint32_t(g_swapChain->getHeight() * Config::ResolutionScale);
device[46] = width == 0 ? 880 : width;
device[47] = height == 0 ? 720 : height;
}
@@ -2588,6 +2649,50 @@ static uint32_t StubFunction()
return 0;
}
static GuestShader* g_movieVertexShader;
static GuestShader* g_moviePixelShader;
static GuestVertexDeclaration* g_movieVertexDeclaration;
static void ScreenShaderInit(be<uint32_t>* a1, uint32_t a2, uint32_t a3, GuestVertexElement* vertexElements)
{
if (g_moviePixelShader == nullptr)
{
g_moviePixelShader = g_userHeap.AllocPhysical<GuestShader>(ResourceType::PixelShader);
g_moviePixelShader->shader = CREATE_SHADER(movie_ps);
}
if (g_movieVertexShader == nullptr)
{
g_movieVertexShader = g_userHeap.AllocPhysical<GuestShader>(ResourceType::VertexShader);
g_movieVertexShader->shader = CREATE_SHADER(movie_vs);
}
if (g_movieVertexDeclaration == nullptr)
g_movieVertexDeclaration = CreateVertexDeclaration(vertexElements);
g_moviePixelShader->AddRef();
g_movieVertexShader->AddRef();
g_movieVertexDeclaration->AddRef();
a1[2] = g_memory.MapVirtual(g_moviePixelShader);
a1[3] = g_memory.MapVirtual(g_movieVertexShader);
a1[4] = g_memory.MapVirtual(g_movieVertexDeclaration);
}
void MovieRendererMidAsmHook(PPCRegister& r3)
{
auto device = reinterpret_cast<GuestDevice*>(g_memory.Translate(r3.u32));
// Force linear filtering & clamp addressing
for (size_t i = 0; i < 3; i++)
{
device->samplerStates[i].data[0] = (device->samplerStates[i].data[0].get() & ~0x7fc00) | 0x24800;
device->samplerStates[i].data[3] = (device->samplerStates[i].data[3].get() & ~0x1f80000) | 0x1280000;
}
device->dirtyFlags[3] = device->dirtyFlags[3].get() | 0xe0000000ull;
}
GUEST_FUNCTION_HOOK(sub_82BD99B0, CreateDevice);
GUEST_FUNCTION_HOOK(sub_82BE6230, DestructResource);
@@ -2653,6 +2758,8 @@ GUEST_FUNCTION_HOOK(sub_82E43FC8, MakePictureData);
GUEST_FUNCTION_HOOK(sub_82E9EE38, SetResolution);
GUEST_FUNCTION_HOOK(sub_82BE77B0, StubFunction);
GUEST_FUNCTION_HOOK(sub_82AE2BF8, ScreenShaderInit);
GUEST_FUNCTION_STUB(sub_822C15D8);
GUEST_FUNCTION_STUB(sub_822C1810);
GUEST_FUNCTION_STUB(sub_82BD97A8);