rexglue-skate3/include/rex/ui/d3d12/d3d12_immediate_drawer.h
2026-05-18 22:41:13 +01:00

161 lines
5.5 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*
* @modified Tom Clay, 2026 - Adapted for ReXGlue runtime
*/
#pragma once
#include <deque>
#include <memory>
#include <utility>
#include <vector>
#include <rex/ui/d3d12/d3d12_api.h>
#include <rex/ui/d3d12/d3d12_descriptor_heap_pool.h>
#include <rex/ui/d3d12/d3d12_provider.h>
#include <rex/ui/d3d12/d3d12_upload_buffer_pool.h>
#include <rex/ui/immediate_drawer.h>
namespace rex::ui::d3d12 {
class D3D12ImmediateDrawer final : public ImmediateDrawer {
public:
static std::unique_ptr<D3D12ImmediateDrawer> Create(const D3D12Provider& provider) {
auto immediate_drawer =
std::unique_ptr<D3D12ImmediateDrawer>(new D3D12ImmediateDrawer(provider));
if (!immediate_drawer->Initialize()) {
return nullptr;
}
return std::move(immediate_drawer);
}
~D3D12ImmediateDrawer();
std::unique_ptr<ImmediateTexture> CreateTexture(uint32_t width, uint32_t height,
ImmediateTextureFilter filter, bool is_repeated,
const uint8_t* data) override;
void Begin(UIDrawContext& ui_draw_context, float coordinate_space_width,
float coordinate_space_height) override;
void BeginDrawBatch(const ImmediateDrawBatch& batch) override;
void Draw(const ImmediateDraw& draw) override;
void EndDrawBatch() override;
void End() override;
protected:
void OnLeavePresenter() override;
private:
enum class SamplerIndex {
kNearestClamp,
kLinearClamp,
kNearestRepeat,
kLinearRepeat,
kCount,
kInvalid = kCount
};
class D3D12ImmediateTexture final : public ImmediateTexture {
public:
static constexpr DXGI_FORMAT kFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
D3D12ImmediateTexture(uint32_t width, uint32_t height, ID3D12Resource* resource,
SamplerIndex sampler_index, D3D12ImmediateDrawer* immediate_drawer,
size_t immediate_drawer_index);
~D3D12ImmediateTexture() override;
ID3D12Resource* resource() const { return resource_.Get(); }
SamplerIndex sampler_index() const { return sampler_index_; }
size_t immediate_drawer_index() const { return immediate_drawer_index_; }
void SetImmediateDrawerIndex(size_t index) { immediate_drawer_index_ = index; }
void OnImmediateDrawerDestroyed();
UINT64 last_usage_submission_index() const { return last_usage_submission_index_; }
void SetLastUsageSubmissionIndex(UINT64 submission_index) {
last_usage_submission_index_ = submission_index;
}
private:
Microsoft::WRL::ComPtr<ID3D12Resource> resource_;
SamplerIndex sampler_index_;
D3D12ImmediateDrawer* immediate_drawer_;
size_t immediate_drawer_index_;
UINT64 last_usage_submission_index_ = 0;
};
D3D12ImmediateDrawer(const D3D12Provider& provider) : provider_(provider) {}
bool Initialize();
void OnImmediateTextureDestroyed(D3D12ImmediateTexture& texture);
void UploadTextures();
const D3D12Provider& provider_;
Microsoft::WRL::ComPtr<ID3D12RootSignature> root_signature_;
enum class RootParameter {
kTexture,
kSampler,
kCoordinateSpaceSizeInv,
kCount
};
Microsoft::WRL::ComPtr<ID3D12PipelineState> pipeline_triangle_;
Microsoft::WRL::ComPtr<ID3D12PipelineState> pipeline_line_;
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> sampler_heap_;
D3D12_CPU_DESCRIPTOR_HANDLE sampler_heap_cpu_start_;
D3D12_GPU_DESCRIPTOR_HANDLE sampler_heap_gpu_start_;
// Only with non-null resources.
std::vector<D3D12ImmediateTexture*> textures_;
struct PendingTextureUpload {
PendingTextureUpload(ID3D12Resource* texture, ID3D12Resource* buffer)
: texture(texture), buffer(buffer) {}
Microsoft::WRL::ComPtr<ID3D12Resource> texture;
Microsoft::WRL::ComPtr<ID3D12Resource> buffer;
};
std::vector<PendingTextureUpload> texture_uploads_pending_;
struct SubmittedTextureUpload {
SubmittedTextureUpload(ID3D12Resource* texture, ID3D12Resource* buffer, UINT64 submission_index)
: texture(texture), buffer(buffer), submission_index(submission_index) {}
Microsoft::WRL::ComPtr<ID3D12Resource> texture;
Microsoft::WRL::ComPtr<ID3D12Resource> buffer;
UINT64 submission_index;
};
std::deque<SubmittedTextureUpload> texture_uploads_submitted_;
std::deque<std::pair<Microsoft::WRL::ComPtr<ID3D12Resource>, UINT64>> textures_deleted_;
std::unique_ptr<D3D12UploadBufferPool> vertex_buffer_pool_;
std::unique_ptr<D3D12DescriptorHeapPool> texture_descriptor_pool_;
// The submission index within the current Begin (or the last, if outside
// one).
UINT64 last_paint_submission_index_ = 0;
// Completed submission index as of the latest Begin, to coarsely skip delayed
// texture deletion.
UINT64 last_completed_submission_index_ = 0;
bool batch_open_ = false;
bool batch_has_index_buffer_;
D3D12_RECT current_scissor_;
D3D_PRIMITIVE_TOPOLOGY current_primitive_topology_;
ID3D12Resource* current_texture_;
uint64_t current_texture_descriptor_heap_index_;
SamplerIndex current_sampler_index_;
};
} // namespace rex::ui::d3d12