Files
Xenia-Canary/src/xenia/ui/d3d12/d3d12_immediate_drawer.cc

157 lines
5.9 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2018 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/ui/d3d12/d3d12_immediate_drawer.h"
#include "xenia/base/logging.h"
namespace xe {
namespace ui {
namespace d3d12 {
class D3D12ImmediateTexture : public ImmediateTexture {
public:
D3D12ImmediateTexture(uint32_t width, uint32_t height)
: ImmediateTexture(width, height) {}
};
D3D12ImmediateDrawer::D3D12ImmediateDrawer(D3D12Context* graphics_context)
: ImmediateDrawer(graphics_context), context_(graphics_context) {}
D3D12ImmediateDrawer::~D3D12ImmediateDrawer() { Shutdown(); }
bool D3D12ImmediateDrawer::Initialize() {
auto provider = context_->GetD3D12Provider();
auto device = provider->GetDevice();
// Create the samplers.
D3D12_DESCRIPTOR_HEAP_DESC sampler_heap_desc;
sampler_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
sampler_heap_desc.NumDescriptors = uint32_t(SamplerIndex::kSamplerCount);
sampler_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
sampler_heap_desc.NodeMask = 0;
if (FAILED(device->CreateDescriptorHeap(&sampler_heap_desc,
IID_PPV_ARGS(&sampler_heap_)))) {
XELOGE("Failed to create immediate drawer sampler descriptor heap");
Shutdown();
return false;
}
sampler_heap_cpu_start_ = sampler_heap_->GetCPUDescriptorHandleForHeapStart();
sampler_heap_gpu_start_ = sampler_heap_->GetGPUDescriptorHandleForHeapStart();
uint32_t sampler_size = provider->GetDescriptorSizeSampler();
// Nearest neighbor, clamp.
D3D12_SAMPLER_DESC sampler_desc;
sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
sampler_desc.MipLODBias = 0.0f;
sampler_desc.MaxAnisotropy = 1;
sampler_desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
sampler_desc.BorderColor[0] = 0.0f;
sampler_desc.BorderColor[1] = 0.0f;
sampler_desc.BorderColor[2] = 0.0f;
sampler_desc.BorderColor[3] = 0.0f;
sampler_desc.MinLOD = 0.0f;
sampler_desc.MaxLOD = 0.0f;
D3D12_CPU_DESCRIPTOR_HANDLE sampler_handle;
sampler_handle.ptr = sampler_heap_cpu_start_.ptr +
uint32_t(SamplerIndex::kNearestClamp) * sampler_size;
device->CreateSampler(&sampler_desc, sampler_handle);
// Bilinear, clamp.
sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
sampler_handle.ptr = sampler_heap_cpu_start_.ptr +
uint32_t(SamplerIndex::kLinearClamp) * sampler_size;
device->CreateSampler(&sampler_desc, sampler_handle);
// Nearest neighbor, repeat.
sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
sampler_handle.ptr = sampler_heap_cpu_start_.ptr +
uint32_t(SamplerIndex::kNearestRepeat) * sampler_size;
device->CreateSampler(&sampler_desc, sampler_handle);
// Bilinear, repeat.
sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
sampler_handle.ptr = sampler_heap_cpu_start_.ptr +
uint32_t(SamplerIndex::kLinearRepeat) * sampler_size;
device->CreateSampler(&sampler_desc, sampler_handle);
// Reset the current state.
current_command_list_ = nullptr;
return true;
}
void D3D12ImmediateDrawer::Shutdown() {
for (auto& texture_upload : texture_uploads_submitted_) {
texture_upload.data_resource->Release();
}
texture_uploads_submitted_.clear();
if (sampler_heap_ != nullptr) {
sampler_heap_->Release();
sampler_heap_ = nullptr;
}
}
std::unique_ptr<ImmediateTexture> D3D12ImmediateDrawer::CreateTexture(
uint32_t width, uint32_t height, ImmediateTextureFilter filter, bool repeat,
const uint8_t* data) {
// TODO(Triang3l): Implement CreateTexture.
auto texture = std::make_unique<D3D12ImmediateTexture>(width, height);
return std::unique_ptr<ImmediateTexture>(texture.release());
}
void D3D12ImmediateDrawer::UpdateTexture(ImmediateTexture* texture,
const uint8_t* data) {
// TODO(Triang3l): Implement UpdateTexture.
}
void D3D12ImmediateDrawer::Begin(int render_target_width,
int render_target_height) {
// Use the compositing command list.
current_command_list_ = context_->GetSwapCommandList();
uint32_t queue_frame = context_->GetCurrentQueueFrame();
uint64_t last_completed_frame = context_->GetLastCompletedFrame();
// Remove temporary buffers for completed texture uploads.
auto erase_uploads_end = texture_uploads_submitted_.begin();
while (erase_uploads_end != texture_uploads_submitted_.end()) {
uint64_t upload_frame = erase_uploads_end->frame;
if (upload_frame > last_completed_frame) {
++erase_uploads_end;
break;
}
erase_uploads_end->data_resource->Release();
++erase_uploads_end;
}
texture_uploads_submitted_.erase(texture_uploads_submitted_.begin(),
erase_uploads_end);
}
void D3D12ImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) {
// TODO(Triang3l): Implement BeginDrawBatch.
}
void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) {
// TODO(Triang3l): Implement Draw.
}
void D3D12ImmediateDrawer::EndDrawBatch() {
// TODO(Triang3l): Implement EndDrawBatch.
}
void D3D12ImmediateDrawer::End() { current_command_list_ = nullptr; }
} // namespace d3d12
} // namespace ui
} // namespace xe