Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions MarathonRecomp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -471,11 +471,11 @@ function(compile_shader FILE_PATH TARGET_NAME)
endfunction()

function(compile_vertex_shader FILE_PATH)
compile_shader(${FILE_PATH} vs_6_0 -fvk-invert-y)
compile_shader(${FILE_PATH} vs_6_0 -fvk-invert-y -DMARATHON_RECOMP)
endfunction()

function(compile_pixel_shader FILE_PATH)
compile_shader(${FILE_PATH} ps_6_0)
compile_shader(${FILE_PATH} ps_6_0 -DMARATHON_RECOMP)
endfunction()

compile_pixel_shader(blend_color_alpha_ps)
Expand Down
131 changes: 127 additions & 4 deletions MarathonRecomp/gpu/video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ struct SharedConstants
float clipPlane[4]{};
bool clipPlaneEnabled{};
float alphaThreshold{};
uint32_t conditionalSurveyIndex{};
uint32_t conditionalRenderingIndex{};
};

// Depth bias values here are only used when the render device has
Expand Down Expand Up @@ -386,8 +388,12 @@ static uint32_t g_intermediaryBackBufferTextureDescriptorIndex;

static std::unique_ptr<RenderPipeline> g_gammaCorrectionPipeline;

struct std::unique_ptr<RenderDescriptorSet> g_textureDescriptorSet;
struct std::unique_ptr<RenderDescriptorSet> g_samplerDescriptorSet;
static std::unique_ptr<RenderDescriptorSet> g_textureDescriptorSet;
static std::unique_ptr<RenderDescriptorSet> g_samplerDescriptorSet;

static constexpr uint32_t CONDITIONAL_SURVEY_MAX = 64;
static std::unique_ptr<RenderBuffer> g_conditionalSurveyBuffer;
static std::unique_ptr<RenderDescriptorSet> g_conditionalSurveyDescriptorSet;

enum
{
Expand Down Expand Up @@ -905,6 +911,8 @@ enum class RenderCommandType
SetStreamSource,
SetIndices,
SetPixelShader,
SetConditionalSurvey,
SetConditionalRendering,
};

struct RenderCommand
Expand Down Expand Up @@ -1068,6 +1076,18 @@ struct RenderCommand
{
GuestShader* shader;
} setPixelShader;

struct
{
bool enabled;
uint32_t index;
} setConditionalSurvey;

struct
{
bool enabled;
uint32_t index;
} setConditionalRendering;
};
};

Expand Down Expand Up @@ -1343,7 +1363,7 @@ static void ProcSetRenderState(const RenderCommand& cmd)
}
case D3DRS_ALPHAREF:
{
SetDirtyValue(g_dirtyStates.pipelineState, g_sharedConstants.alphaThreshold, float(value) / 256.0f);
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.alphaThreshold, float(value) / 256.0f);
break;
}
case D3DRS_ALPHABLENDENABLE:
Expand Down Expand Up @@ -1505,7 +1525,7 @@ static bool DetectWine()
}
#endif

static constexpr size_t TEXTURE_DESCRIPTOR_SIZE = 65536;
static constexpr size_t TEXTURE_DESCRIPTOR_SIZE = 32768;
static constexpr size_t SAMPLER_DESCRIPTOR_SIZE = 1024;

static std::unique_ptr<GuestTexture> g_imFontTexture;
Expand Down Expand Up @@ -1800,6 +1820,7 @@ static void BeginCommandList()
commandList->setGraphicsDescriptorSet(g_textureDescriptorSet.get(), 1);
commandList->setGraphicsDescriptorSet(g_textureDescriptorSet.get(), 2);
commandList->setGraphicsDescriptorSet(g_samplerDescriptorSet.get(), 3);
commandList->setGraphicsDescriptorSet(g_conditionalSurveyDescriptorSet.get(), 4);

g_readyForCommands = true;
g_readyForCommands.notify_one();
Expand Down Expand Up @@ -2138,6 +2159,23 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)

pipelineLayoutBuilder.addDescriptorSet(descriptorSetBuilder);

RenderBufferDesc conditionalSurveyBufferDesc;
conditionalSurveyBufferDesc.size = CONDITIONAL_SURVEY_MAX * sizeof(uint32_t);
conditionalSurveyBufferDesc.heapType = RenderHeapType::DEFAULT;
conditionalSurveyBufferDesc.flags = RenderBufferFlag::STORAGE | RenderTextureFlag::UNORDERED_ACCESS;
g_conditionalSurveyBuffer = g_device->createBuffer(conditionalSurveyBufferDesc);

RenderDescriptorSetBuilder conditionalSurveyDescriptorSetBuilder;
conditionalSurveyDescriptorSetBuilder.begin();
conditionalSurveyDescriptorSetBuilder.addReadWriteStructuredBuffer(0);
conditionalSurveyDescriptorSetBuilder.end();
g_conditionalSurveyDescriptorSet = conditionalSurveyDescriptorSetBuilder.create(g_device.get());

RenderBufferStructuredView conditionalSurveyStructuredView(sizeof(uint32_t));
g_conditionalSurveyDescriptorSet->setBuffer(0, g_conditionalSurveyBuffer.get(), 0, &conditionalSurveyStructuredView);

pipelineLayoutBuilder.addDescriptorSet(conditionalSurveyDescriptorSetBuilder);

if (g_backend != Backend::D3D12)
{
pipelineLayoutBuilder.addPushConstant(0, 4, 24, RenderShaderStageFlag::VERTEX | RenderShaderStageFlag::PIXEL);
Expand Down Expand Up @@ -5585,6 +5623,84 @@ static void ProcSetPixelShader(const RenderCommand& cmd)
SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.pixelShader, shader);
}

static void BeginConditionalSurvey(GuestDevice* device, uint32_t index)
{
assert(index < CONDITIONAL_SURVEY_MAX && "Invalid conditional survey index.");

RenderCommand cmd;
cmd.type = RenderCommandType::SetConditionalSurvey;
cmd.setConditionalSurvey.enabled = true;
cmd.setConditionalSurvey.index = index;
g_renderQueue.enqueue(cmd);
}

static void EndConditionalSurvey(GuestDevice* device)
{
RenderCommand cmd;
cmd.type = RenderCommandType::SetConditionalSurvey;
cmd.setConditionalSurvey.enabled = false;
cmd.setConditionalSurvey.index = 0;
g_renderQueue.enqueue(cmd);
}

static void ProcSetConditionalSurvey(const RenderCommand& cmd)
{
uint32_t specConstants = g_pipelineState.specConstants;
if (cmd.setConditionalSurvey.enabled)
{
// Clear previous survey result first.
auto uploadBuffer = g_device->createBuffer(RenderBufferDesc::UploadBuffer(sizeof(uint32_t)));
memset(uploadBuffer->map(), 0, sizeof(uint32_t));
uploadBuffer->unmap();

auto& commandList = g_commandLists[g_frame];
commandList->barriers(RenderBarrierStage::COPY, RenderBufferBarrier(g_conditionalSurveyBuffer.get(), RenderBufferAccess::WRITE));
commandList->copyBufferRegion(g_conditionalSurveyBuffer->at(cmd.setConditionalSurvey.index * sizeof(uint32_t)), uploadBuffer->at(0), sizeof(uint32_t));
commandList->barriers(RenderBarrierStage::GRAPHICS, RenderBufferBarrier(g_conditionalSurveyBuffer.get(), RenderBufferAccess::READ | RenderBufferAccess::WRITE));

g_tempBuffers[g_frame].emplace_back(std::move(uploadBuffer));

specConstants |= SPEC_CONSTANT_CONDITIONAL_SURVEY;
}
else
specConstants &= ~SPEC_CONSTANT_CONDITIONAL_SURVEY;

SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.specConstants, specConstants);
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.conditionalSurveyIndex, cmd.setConditionalSurvey.index);
}

static void BeginConditionalRendering(GuestDevice* device, uint32_t index)
{
assert(index < CONDITIONAL_SURVEY_MAX && "Invalid conditional rendering index.");

RenderCommand cmd;
cmd.type = RenderCommandType::SetConditionalRendering;
cmd.setConditionalRendering.enabled = true;
cmd.setConditionalRendering.index = index;
g_renderQueue.enqueue(cmd);
}

static void EndConditionalRendering(GuestDevice* device)
{
RenderCommand cmd;
cmd.type = RenderCommandType::SetConditionalRendering;
cmd.setConditionalRendering.enabled = false;
cmd.setConditionalRendering.index = 0;
g_renderQueue.enqueue(cmd);
}

static void ProcSetConditionalRendering(const RenderCommand& cmd)
{
uint32_t specConstants = g_pipelineState.specConstants;
if (cmd.setConditionalRendering.enabled)
specConstants |= SPEC_CONSTANT_CONDITIONAL_RENDERING;
else
specConstants &= ~SPEC_CONSTANT_CONDITIONAL_RENDERING;

SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.specConstants, specConstants);
SetDirtyValue(g_dirtyStates.sharedConstants, g_sharedConstants.conditionalRenderingIndex, cmd.setConditionalRendering.index);
}

static void SetClipPlane(GuestDevice* device, uint32_t index, const be<float>* plane)
{
if (index != 0)
Expand Down Expand Up @@ -5643,6 +5759,8 @@ static std::thread g_renderThread([]
case RenderCommandType::SetStreamSource: ProcSetStreamSource(cmd); break;
case RenderCommandType::SetIndices: ProcSetIndices(cmd); break;
case RenderCommandType::SetPixelShader: ProcSetPixelShader(cmd); break;
case RenderCommandType::SetConditionalSurvey: ProcSetConditionalSurvey(cmd); break;
case RenderCommandType::SetConditionalRendering: ProcSetConditionalRendering(cmd); break;
default: assert(false && "Unrecognized render command type."); break;
}
}
Expand Down Expand Up @@ -8263,6 +8381,11 @@ GUEST_FUNCTION_HOOK(sub_82543AC8, SetIndices); // replaced
GUEST_FUNCTION_HOOK(sub_82548608, CreatePixelShader); // replaced
GUEST_FUNCTION_HOOK(sub_82546BD8, SetPixelShader);

GUEST_FUNCTION_HOOK(sub_82636BF8, BeginConditionalSurvey);
GUEST_FUNCTION_HOOK(sub_82636C08, EndConditionalSurvey);
GUEST_FUNCTION_HOOK(sub_82636C10, BeginConditionalRendering);
GUEST_FUNCTION_HOOK(sub_82636C18, EndConditionalRendering);

GUEST_FUNCTION_HOOK(sub_8253B760, IsSet);

GUEST_FUNCTION_HOOK(sub_82543CF0, SetClipPlane); // replaced
Expand Down
3 changes: 3 additions & 0 deletions MarathonRecomp/gpu/video.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
#define SPEC_CONSTANT_ALPHA_TO_COVERAGE (1 << 3)
#define SPEC_CONSTANT_REVERSE_Z (1 << 4)

#define SPEC_CONSTANT_CONDITIONAL_SURVEY (1 << 5)
#define SPEC_CONSTANT_CONDITIONAL_RENDERING (1 << 6)

#define LOAD_ZSTD_TEXTURE(name) LoadTexture(decompressZstd(name, name##_uncompressed_size).get(), name##_uncompressed_size)

using namespace plume;
Expand Down
1 change: 1 addition & 0 deletions MarathonRecompLib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ target_compile_definitions(XenosRecomp PRIVATE
XENOS_RECOMP_INPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/private/shader\"
XENOS_RECOMP_OUTPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/shader/shader_cache.cpp\"
XENOS_RECOMP_INCLUDE_INPUT=\"${XENOS_RECOMP_INCLUDE}\"
MARATHON_RECOMP
)

file(GLOB XENOS_RECOMP_SOURCES
Expand Down
Loading