[UI] Remove pass-unfriendly UpdateTexture of ImmediateDrawer

This commit is contained in:
Triang3l 2020-09-20 20:34:22 +03:00
parent 183c7eee2b
commit fc55b1f81d
9 changed files with 275 additions and 271 deletions

View File

@ -10,6 +10,9 @@
#include "xenia/ui/d3d12/d3d12_immediate_drawer.h" #include "xenia/ui/d3d12/d3d12_immediate_drawer.h"
#include <cstring> #include <cstring>
#include <memory>
#include <utility>
#include <vector>
#include "xenia/base/assert.h" #include "xenia/base/assert.h"
#include "xenia/base/logging.h" #include "xenia/base/logging.h"
@ -28,95 +31,48 @@ namespace d3d12 {
class D3D12ImmediateTexture : public ImmediateTexture { class D3D12ImmediateTexture : public ImmediateTexture {
public: public:
static constexpr DXGI_FORMAT kFormat = DXGI_FORMAT_R8G8B8A8_UNORM; static constexpr DXGI_FORMAT kFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
D3D12ImmediateTexture(uint32_t width, uint32_t height, D3D12ImmediateTexture(uint32_t width, uint32_t height,
ImmediateTextureFilter filter, bool repeat); ID3D12Resource* resource_if_exists,
ImmediateTextureFilter filter, bool is_repeated);
~D3D12ImmediateTexture() override; ~D3D12ImmediateTexture() override;
ID3D12Resource* resource() const { return resource_; }
bool Initialize(D3D12Provider& provider); ImmediateTextureFilter filter() const { return filter_; }
void Shutdown(); bool is_repeated() const { return is_repeated_; }
ID3D12Resource* GetResource() const { return resource_; }
void Transition(D3D12_RESOURCE_STATES new_state,
ID3D12GraphicsCommandList* command_list);
ImmediateTextureFilter GetFilter() const { return filter_; }
bool IsRepeated() const { return repeat_; }
private: private:
ID3D12Resource* resource_ = nullptr; ID3D12Resource* resource_;
D3D12_RESOURCE_STATES state_;
ImmediateTextureFilter filter_; ImmediateTextureFilter filter_;
bool repeat_; bool is_repeated_;
}; };
D3D12ImmediateTexture::D3D12ImmediateTexture(uint32_t width, uint32_t height, D3D12ImmediateTexture::D3D12ImmediateTexture(uint32_t width, uint32_t height,
ID3D12Resource* resource_if_exists,
ImmediateTextureFilter filter, ImmediateTextureFilter filter,
bool repeat) bool is_repeated)
: ImmediateTexture(width, height), filter_(filter), repeat_(repeat) { : ImmediateTexture(width, height),
resource_(resource_if_exists),
filter_(filter),
is_repeated_(is_repeated) {
if (resource_) {
resource_->AddRef();
}
handle = reinterpret_cast<uintptr_t>(this); handle = reinterpret_cast<uintptr_t>(this);
} }
D3D12ImmediateTexture::~D3D12ImmediateTexture() { Shutdown(); } D3D12ImmediateTexture::~D3D12ImmediateTexture() {
if (resource_) {
bool D3D12ImmediateTexture::Initialize(D3D12Provider& provider) {
// The first operation will likely be copying the contents.
state_ = D3D12_RESOURCE_STATE_COPY_DEST;
D3D12_RESOURCE_DESC resource_desc;
resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
resource_desc.Alignment = 0;
resource_desc.Width = width;
resource_desc.Height = height;
resource_desc.DepthOrArraySize = 1;
resource_desc.MipLevels = 1;
resource_desc.Format = kFormat;
resource_desc.SampleDesc.Count = 1;
resource_desc.SampleDesc.Quality = 0;
resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE;
if (FAILED(provider.GetDevice()->CreateCommittedResource(
&util::kHeapPropertiesDefault, provider.GetHeapFlagCreateNotZeroed(),
&resource_desc, state_, nullptr, IID_PPV_ARGS(&resource_)))) {
XELOGE("Failed to create a {}x{} texture for immediate drawing", width,
height);
return false;
}
return true;
}
void D3D12ImmediateTexture::Shutdown() {
if (resource_ != nullptr) {
resource_->Release(); resource_->Release();
resource_ = nullptr;
} }
} }
void D3D12ImmediateTexture::Transition(
D3D12_RESOURCE_STATES new_state, ID3D12GraphicsCommandList* command_list) {
if (resource_ == nullptr || state_ == new_state) {
return;
}
D3D12_RESOURCE_BARRIER barrier;
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = resource_;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
barrier.Transition.StateBefore = state_;
barrier.Transition.StateAfter = new_state;
command_list->ResourceBarrier(1, &barrier);
state_ = new_state;
}
D3D12ImmediateDrawer::D3D12ImmediateDrawer(D3D12Context& graphics_context) D3D12ImmediateDrawer::D3D12ImmediateDrawer(D3D12Context& graphics_context)
: ImmediateDrawer(&graphics_context), context_(graphics_context) {} : ImmediateDrawer(&graphics_context), context_(graphics_context) {}
D3D12ImmediateDrawer::~D3D12ImmediateDrawer() { Shutdown(); } D3D12ImmediateDrawer::~D3D12ImmediateDrawer() { Shutdown(); }
bool D3D12ImmediateDrawer::Initialize() { bool D3D12ImmediateDrawer::Initialize() {
auto& provider = context_.GetD3D12Provider(); const D3D12Provider& provider = context_.GetD3D12Provider();
auto device = provider.GetDevice(); ID3D12Device* device = provider.GetDevice();
// Create the root signature. // Create the root signature.
D3D12_ROOT_PARAMETER root_parameters[size_t(RootParameter::kCount)]; D3D12_ROOT_PARAMETER root_parameters[size_t(RootParameter::kCount)];
@ -174,20 +130,20 @@ bool D3D12ImmediateDrawer::Initialize() {
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
root_signature_ = util::CreateRootSignature(provider, root_signature_desc); root_signature_ = util::CreateRootSignature(provider, root_signature_desc);
if (root_signature_ == nullptr) { if (root_signature_ == nullptr) {
XELOGE("Failed to create the immediate drawer root signature"); XELOGE("Failed to create the Direct3D 12 immediate drawer root signature");
Shutdown(); Shutdown();
return false; return false;
} }
// Create the pipeline states. // Create the pipeline states.
D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeline_desc = {}; D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeline_state_desc = {};
pipeline_desc.pRootSignature = root_signature_; pipeline_state_desc.pRootSignature = root_signature_;
pipeline_desc.VS.pShaderBytecode = immediate_vs; pipeline_state_desc.VS.pShaderBytecode = immediate_vs;
pipeline_desc.VS.BytecodeLength = sizeof(immediate_vs); pipeline_state_desc.VS.BytecodeLength = sizeof(immediate_vs);
pipeline_desc.PS.pShaderBytecode = immediate_ps; pipeline_state_desc.PS.pShaderBytecode = immediate_ps;
pipeline_desc.PS.BytecodeLength = sizeof(immediate_ps); pipeline_state_desc.PS.BytecodeLength = sizeof(immediate_ps);
D3D12_RENDER_TARGET_BLEND_DESC& pipeline_blend_desc = D3D12_RENDER_TARGET_BLEND_DESC& pipeline_blend_desc =
pipeline_desc.BlendState.RenderTarget[0]; pipeline_state_desc.BlendState.RenderTarget[0];
pipeline_blend_desc.BlendEnable = TRUE; pipeline_blend_desc.BlendEnable = TRUE;
pipeline_blend_desc.SrcBlend = D3D12_BLEND_SRC_ALPHA; pipeline_blend_desc.SrcBlend = D3D12_BLEND_SRC_ALPHA;
pipeline_blend_desc.DestBlend = D3D12_BLEND_INV_SRC_ALPHA; pipeline_blend_desc.DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
@ -199,11 +155,11 @@ bool D3D12ImmediateDrawer::Initialize() {
pipeline_blend_desc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_RED | pipeline_blend_desc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_RED |
D3D12_COLOR_WRITE_ENABLE_GREEN | D3D12_COLOR_WRITE_ENABLE_GREEN |
D3D12_COLOR_WRITE_ENABLE_BLUE; D3D12_COLOR_WRITE_ENABLE_BLUE;
pipeline_desc.SampleMask = UINT_MAX; pipeline_state_desc.SampleMask = UINT_MAX;
pipeline_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; pipeline_state_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
pipeline_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; pipeline_state_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
pipeline_desc.RasterizerState.FrontCounterClockwise = FALSE; pipeline_state_desc.RasterizerState.FrontCounterClockwise = FALSE;
pipeline_desc.RasterizerState.DepthClipEnable = TRUE; pipeline_state_desc.RasterizerState.DepthClipEnable = TRUE;
D3D12_INPUT_ELEMENT_DESC pipeline_input_elements[3] = {}; D3D12_INPUT_ELEMENT_DESC pipeline_input_elements[3] = {};
pipeline_input_elements[0].SemanticName = "POSITION"; pipeline_input_elements[0].SemanticName = "POSITION";
pipeline_input_elements[0].Format = DXGI_FORMAT_R32G32_FLOAT; pipeline_input_elements[0].Format = DXGI_FORMAT_R32G32_FLOAT;
@ -215,23 +171,29 @@ bool D3D12ImmediateDrawer::Initialize() {
pipeline_input_elements[2].Format = DXGI_FORMAT_R8G8B8A8_UNORM; pipeline_input_elements[2].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
pipeline_input_elements[2].AlignedByteOffset = pipeline_input_elements[2].AlignedByteOffset =
offsetof(ImmediateVertex, color); offsetof(ImmediateVertex, color);
pipeline_desc.InputLayout.pInputElementDescs = pipeline_input_elements; pipeline_state_desc.InputLayout.pInputElementDescs = pipeline_input_elements;
pipeline_desc.InputLayout.NumElements = pipeline_state_desc.InputLayout.NumElements =
UINT(xe::countof(pipeline_input_elements)); UINT(xe::countof(pipeline_input_elements));
pipeline_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; pipeline_state_desc.PrimitiveTopologyType =
pipeline_desc.NumRenderTargets = 1; D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
pipeline_desc.RTVFormats[0] = D3D12Context::kSwapChainFormat; pipeline_state_desc.NumRenderTargets = 1;
pipeline_desc.SampleDesc.Count = 1; pipeline_state_desc.RTVFormats[0] = D3D12Context::kSwapChainFormat;
pipeline_state_desc.SampleDesc.Count = 1;
if (FAILED(device->CreateGraphicsPipelineState( if (FAILED(device->CreateGraphicsPipelineState(
&pipeline_desc, IID_PPV_ARGS(&pipeline_triangle_)))) { &pipeline_state_desc, IID_PPV_ARGS(&pipeline_state_triangle_)))) {
XELOGE("Failed to create immediate drawer triangle pipeline state"); XELOGE(
"Failed to create the Direct3D 12 immediate drawer triangle pipeline "
"state");
Shutdown(); Shutdown();
return false; return false;
} }
pipeline_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; pipeline_state_desc.PrimitiveTopologyType =
D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
if (FAILED(device->CreateGraphicsPipelineState( if (FAILED(device->CreateGraphicsPipelineState(
&pipeline_desc, IID_PPV_ARGS(&pipeline_line_)))) { &pipeline_state_desc, IID_PPV_ARGS(&pipeline_state_line_)))) {
XELOGE("Failed to create immediate drawer line pipeline state"); XELOGE(
"Failed to create the Direct3D 12 immediate drawer line pipeline "
"state");
Shutdown(); Shutdown();
return false; return false;
} }
@ -244,7 +206,9 @@ bool D3D12ImmediateDrawer::Initialize() {
sampler_heap_desc.NodeMask = 0; sampler_heap_desc.NodeMask = 0;
if (FAILED(device->CreateDescriptorHeap(&sampler_heap_desc, if (FAILED(device->CreateDescriptorHeap(&sampler_heap_desc,
IID_PPV_ARGS(&sampler_heap_)))) { IID_PPV_ARGS(&sampler_heap_)))) {
XELOGE("Failed to create immediate drawer sampler descriptor heap"); XELOGE(
"Failed to create the Direct3D 12 immediate drawer sampler descriptor "
"heap");
Shutdown(); Shutdown();
return false; return false;
} }
@ -293,8 +257,6 @@ bool D3D12ImmediateDrawer::Initialize() {
vertex_buffer_pool_ = std::make_unique<D3D12UploadBufferPool>(provider); vertex_buffer_pool_ = std::make_unique<D3D12UploadBufferPool>(provider);
texture_descriptor_pool_ = std::make_unique<D3D12DescriptorHeapPool>( texture_descriptor_pool_ = std::make_unique<D3D12DescriptorHeapPool>(
device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 2048); device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 2048);
texture_descriptor_pool_heap_index_ =
D3D12DescriptorHeapPool::kHeapIndexInvalid;
// Reset the current state. // Reset the current state.
current_command_list_ = nullptr; current_command_list_ = nullptr;
@ -306,11 +268,13 @@ bool D3D12ImmediateDrawer::Initialize() {
void D3D12ImmediateDrawer::Shutdown() { void D3D12ImmediateDrawer::Shutdown() {
for (auto& texture_upload : texture_uploads_submitted_) { for (auto& texture_upload : texture_uploads_submitted_) {
texture_upload.buffer->Release(); texture_upload.buffer->Release();
texture_upload.texture->Release();
} }
texture_uploads_submitted_.clear(); texture_uploads_submitted_.clear();
for (auto& texture_upload : texture_uploads_pending_) { for (auto& texture_upload : texture_uploads_pending_) {
texture_upload.buffer->Release(); texture_upload.buffer->Release();
texture_upload.texture->Release();
} }
texture_uploads_pending_.clear(); texture_uploads_pending_.clear();
@ -319,8 +283,8 @@ void D3D12ImmediateDrawer::Shutdown() {
util::ReleaseAndNull(sampler_heap_); util::ReleaseAndNull(sampler_heap_);
util::ReleaseAndNull(pipeline_line_); util::ReleaseAndNull(pipeline_state_line_);
util::ReleaseAndNull(pipeline_triangle_); util::ReleaseAndNull(pipeline_state_triangle_);
util::ReleaseAndNull(root_signature_); util::ReleaseAndNull(root_signature_);
} }
@ -328,93 +292,97 @@ void D3D12ImmediateDrawer::Shutdown() {
std::unique_ptr<ImmediateTexture> D3D12ImmediateDrawer::CreateTexture( std::unique_ptr<ImmediateTexture> D3D12ImmediateDrawer::CreateTexture(
uint32_t width, uint32_t height, ImmediateTextureFilter filter, bool repeat, uint32_t width, uint32_t height, ImmediateTextureFilter filter, bool repeat,
const uint8_t* data) { const uint8_t* data) {
auto texture = const D3D12Provider& provider = context_.GetD3D12Provider();
std::make_unique<D3D12ImmediateTexture>(width, height, filter, repeat); ID3D12Device* device = provider.GetDevice();
texture->Initialize(context_.GetD3D12Provider()); D3D12_HEAP_FLAGS heap_flag_create_not_zeroed =
if (data != nullptr) { provider.GetHeapFlagCreateNotZeroed();
UpdateTexture(texture.get(), data);
}
return std::unique_ptr<ImmediateTexture>(texture.release());
}
void D3D12ImmediateDrawer::UpdateTexture(ImmediateTexture* texture, D3D12_RESOURCE_DESC resource_desc;
const uint8_t* data) { resource_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
D3D12ImmediateTexture* d3d_texture = resource_desc.Alignment = 0;
static_cast<D3D12ImmediateTexture*>(texture); resource_desc.Width = width;
ID3D12Resource* texture_resource = d3d_texture->GetResource(); resource_desc.Height = height;
if (texture_resource == nullptr) { resource_desc.DepthOrArraySize = 1;
return; resource_desc.MipLevels = 1;
} resource_desc.Format = D3D12ImmediateTexture::kFormat;
uint32_t width = d3d_texture->width, height = d3d_texture->height; resource_desc.SampleDesc.Count = 1;
resource_desc.SampleDesc.Quality = 0;
auto& provider = context_.GetD3D12Provider(); resource_desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
auto device = provider.GetDevice(); resource_desc.Flags = D3D12_RESOURCE_FLAG_NONE;
ID3D12Resource* resource;
// Create and fill the upload buffer. if (SUCCEEDED(provider.GetDevice()->CreateCommittedResource(
D3D12_RESOURCE_DESC texture_desc = texture_resource->GetDesc(); &util::kHeapPropertiesDefault, heap_flag_create_not_zeroed,
D3D12_PLACED_SUBRESOURCE_FOOTPRINT upload_footprint; &resource_desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr,
UINT64 upload_size; IID_PPV_ARGS(&resource)))) {
device->GetCopyableFootprints(&texture_desc, 0, 1, 0, &upload_footprint, // Create and fill the upload buffer.
nullptr, nullptr, &upload_size); D3D12_PLACED_SUBRESOURCE_FOOTPRINT upload_footprint;
D3D12_RESOURCE_DESC buffer_desc; UINT64 upload_size;
util::FillBufferResourceDesc(buffer_desc, upload_size, device->GetCopyableFootprints(&resource_desc, 0, 1, 0, &upload_footprint,
D3D12_RESOURCE_FLAG_NONE); nullptr, nullptr, &upload_size);
ID3D12Resource* buffer; D3D12_RESOURCE_DESC upload_buffer_desc;
if (FAILED(device->CreateCommittedResource( util::FillBufferResourceDesc(upload_buffer_desc, upload_size,
&util::kHeapPropertiesUpload, provider.GetHeapFlagCreateNotZeroed(), D3D12_RESOURCE_FLAG_NONE);
&buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, ID3D12Resource* upload_buffer;
IID_PPV_ARGS(&buffer)))) { if (SUCCEEDED(device->CreateCommittedResource(
XELOGE( &util::kHeapPropertiesUpload, heap_flag_create_not_zeroed,
"Failed to create an upload buffer for a {}x{} texture for " &upload_buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr,
"immediate drawing", IID_PPV_ARGS(&upload_buffer)))) {
width, height); D3D12_RANGE upload_buffer_read_range;
return; upload_buffer_read_range.Begin = 0;
} upload_buffer_read_range.End = 0;
D3D12_RANGE buffer_read_range; void* upload_buffer_mapping;
buffer_read_range.Begin = 0; if (SUCCEEDED(upload_buffer->Map(0, &upload_buffer_read_range,
buffer_read_range.End = 0; &upload_buffer_mapping))) {
void* buffer_mapping; uint8_t* upload_buffer_row =
if (FAILED(buffer->Map(0, &buffer_read_range, &buffer_mapping))) { reinterpret_cast<uint8_t*>(upload_buffer_mapping) +
XELOGE( upload_footprint.Offset;
"Failed to map an upload buffer for a {}x{} texture for immediate " const uint8_t* data_row = data;
"drawing", for (uint32_t i = 0; i < height; ++i) {
width, height); std::memcpy(upload_buffer_row, data_row, width * 4);
buffer->Release(); data_row += width * 4;
return; upload_buffer_row += upload_footprint.Footprint.RowPitch;
} }
uint8_t* buffer_row = upload_buffer->Unmap(0, nullptr);
reinterpret_cast<uint8_t*>(buffer_mapping) + upload_footprint.Offset; // Defer uploading and transition to the next draw.
for (uint32_t i = 0; i < height; ++i) { PendingTextureUpload pending_upload;
std::memcpy(buffer_row, data, width * 4); // While the upload has not been yet completed, keep a reference to the
data += width * 4; // resource because its lifetime is not tied to that of the
buffer_row += upload_footprint.Footprint.RowPitch; // ImmediateTexture (and thus to context's submissions) now.
} resource->AddRef();
buffer->Unmap(0, nullptr); pending_upload.texture = resource;
pending_upload.buffer = upload_buffer;
if (current_command_list_ != nullptr) { texture_uploads_pending_.push_back(pending_upload);
// Upload the texture right now if we can. } else {
d3d_texture->Transition(D3D12_RESOURCE_STATE_COPY_DEST, XELOGE(
current_command_list_); "Failed to map a Direct3D 12 upload buffer for a {}x{} texture for "
D3D12_TEXTURE_COPY_LOCATION location_source, location_dest; "immediate drawing",
location_source.pResource = buffer; width, height);
location_source.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; upload_buffer->Release();
location_source.PlacedFootprint = upload_footprint; resource->Release();
location_dest.pResource = texture_resource; resource = nullptr;
location_dest.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; }
location_dest.SubresourceIndex = 0; } else {
current_command_list_->CopyTextureRegion(&location_dest, 0, 0, 0, XELOGE(
&location_source, nullptr); "Failed to create a Direct3D 12 upload buffer for a {}x{} texture "
SubmittedTextureUpload submitted_upload; "for immediate drawing",
submitted_upload.buffer = buffer; width, height);
submitted_upload.fence_value = context_.GetSwapCurrentFenceValue(); resource->Release();
texture_uploads_submitted_.push_back(submitted_upload); resource = nullptr;
}
} else { } else {
// Defer uploading to the next frame when there's a command list. XELOGE("Failed to create a {}x{} Direct3D 12 texture for immediate drawing",
PendingTextureUpload pending_upload; width, height);
pending_upload.texture = texture; resource = nullptr;
pending_upload.buffer = buffer;
texture_uploads_pending_.push_back(pending_upload);
} }
std::unique_ptr<D3D12ImmediateTexture> texture =
std::make_unique<D3D12ImmediateTexture>(width, height, resource, filter,
repeat);
if (resource) {
// D3D12ImmediateTexture now holds a reference.
resource->Release();
}
return std::move(texture);
} }
void D3D12ImmediateDrawer::Begin(int render_target_width, void D3D12ImmediateDrawer::Begin(int render_target_width,
@ -422,7 +390,7 @@ void D3D12ImmediateDrawer::Begin(int render_target_width,
assert_null(current_command_list_); assert_null(current_command_list_);
assert_false(batch_open_); assert_false(batch_open_);
auto device = context_.GetD3D12Provider().GetDevice(); ID3D12Device* device = context_.GetD3D12Provider().GetDevice();
// Use the compositing command list. // Use the compositing command list.
current_command_list_ = context_.GetSwapCommandList(); current_command_list_ = context_.GetSwapCommandList();
@ -430,7 +398,7 @@ void D3D12ImmediateDrawer::Begin(int render_target_width,
uint64_t completed_fence_value = context_.GetSwapCompletedFenceValue(); uint64_t completed_fence_value = context_.GetSwapCompletedFenceValue();
uint64_t current_fence_value = context_.GetSwapCurrentFenceValue(); uint64_t current_fence_value = context_.GetSwapCurrentFenceValue();
// Remove temporary buffers for completed texture uploads. // Release upload buffers for completed texture uploads.
auto erase_uploads_end = texture_uploads_submitted_.begin(); auto erase_uploads_end = texture_uploads_submitted_.begin();
while (erase_uploads_end != texture_uploads_submitted_.end()) { while (erase_uploads_end != texture_uploads_submitted_.end()) {
uint64_t upload_fence_value = erase_uploads_end->fence_value; uint64_t upload_fence_value = erase_uploads_end->fence_value;
@ -439,42 +407,15 @@ void D3D12ImmediateDrawer::Begin(int render_target_width,
break; break;
} }
erase_uploads_end->buffer->Release(); erase_uploads_end->buffer->Release();
// Release the texture reference held for uploading.
erase_uploads_end->texture->Release();
++erase_uploads_end; ++erase_uploads_end;
} }
texture_uploads_submitted_.erase(texture_uploads_submitted_.begin(), texture_uploads_submitted_.erase(texture_uploads_submitted_.begin(),
erase_uploads_end); erase_uploads_end);
// Submit texture updates that happened between frames.
while (!texture_uploads_pending_.empty()) {
const PendingTextureUpload& pending_upload =
texture_uploads_pending_.back();
D3D12ImmediateTexture* texture =
static_cast<D3D12ImmediateTexture*>(pending_upload.texture);
texture->Transition(D3D12_RESOURCE_STATE_COPY_DEST, current_command_list_);
ID3D12Resource* texture_resource = texture->GetResource();
D3D12_RESOURCE_DESC texture_desc = texture_resource->GetDesc();
D3D12_TEXTURE_COPY_LOCATION location_source, location_dest;
location_source.pResource = pending_upload.buffer;
location_source.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
device->GetCopyableFootprints(&texture_desc, 0, 1, 0,
&location_source.PlacedFootprint, nullptr,
nullptr, nullptr);
location_dest.pResource = texture_resource;
location_dest.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
location_dest.SubresourceIndex = 0;
current_command_list_->CopyTextureRegion(&location_dest, 0, 0, 0,
&location_source, nullptr);
SubmittedTextureUpload submitted_upload;
submitted_upload.buffer = pending_upload.buffer;
submitted_upload.fence_value = current_fence_value;
texture_uploads_submitted_.push_back(submitted_upload);
texture_uploads_pending_.pop_back();
}
vertex_buffer_pool_->Reclaim(completed_fence_value); vertex_buffer_pool_->Reclaim(completed_fence_value);
texture_descriptor_pool_->Reclaim(completed_fence_value); texture_descriptor_pool_->Reclaim(completed_fence_value);
texture_descriptor_pool_heap_index_ =
D3D12DescriptorHeapPool::kHeapIndexInvalid;
current_render_target_width_ = render_target_width; current_render_target_width_ = render_target_width;
current_render_target_height_ = render_target_height; current_render_target_height_ = render_target_height;
@ -486,10 +427,6 @@ void D3D12ImmediateDrawer::Begin(int render_target_width,
viewport.MinDepth = 0.0f; viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f; viewport.MaxDepth = 1.0f;
current_command_list_->RSSetViewports(1, &viewport); current_command_list_->RSSetViewports(1, &viewport);
current_scissor_.left = 0;
current_scissor_.top = 0;
current_scissor_.right = 0;
current_scissor_.bottom = 0;
current_command_list_->SetGraphicsRootSignature(root_signature_); current_command_list_->SetGraphicsRootSignature(root_signature_);
float viewport_inv_size[2]; float viewport_inv_size[2];
@ -498,8 +435,15 @@ void D3D12ImmediateDrawer::Begin(int render_target_width,
current_command_list_->SetGraphicsRoot32BitConstants( current_command_list_->SetGraphicsRoot32BitConstants(
UINT(RootParameter::kViewportSizeInv), 2, viewport_inv_size, 0); UINT(RootParameter::kViewportSizeInv), 2, viewport_inv_size, 0);
current_scissor_.left = 0;
current_scissor_.top = 0;
current_scissor_.right = 0;
current_scissor_.bottom = 0;
current_primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; current_primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
current_texture_ = nullptr; current_texture_ = nullptr;
current_texture_descriptor_heap_index_ =
D3D12DescriptorHeapPool::kHeapIndexInvalid;
current_sampler_index_ = SamplerIndex::kInvalid; current_sampler_index_ = SamplerIndex::kInvalid;
} }
@ -554,9 +498,6 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) {
return; return;
} }
auto& provider = context_.GetD3D12Provider();
auto device = provider.GetDevice();
// Set the scissor rectangle if enabled. // Set the scissor rectangle if enabled.
D3D12_RECT scissor; D3D12_RECT scissor;
if (draw.scissor) { if (draw.scissor) {
@ -583,43 +524,56 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) {
current_command_list_->RSSetScissorRects(1, &scissor); current_command_list_->RSSetScissorRects(1, &scissor);
} }
// Bind the texture. // Ensure texture data is available if any texture is loaded, upload all in a
// batch, then transition all at once.
UploadTextures();
// Bind the texture. If this is the first draw in a frame, the descriptor heap
// index will be invalid initially, and the texture will be bound regardless
// of what's in current_texture_.
auto texture = reinterpret_cast<D3D12ImmediateTexture*>(draw.texture_handle); auto texture = reinterpret_cast<D3D12ImmediateTexture*>(draw.texture_handle);
ID3D12Resource* texture_resource; ID3D12Resource* texture_resource = texture ? texture->resource() : nullptr;
if (texture != nullptr) { bool bind_texture = current_texture_ != texture_resource;
texture->Transition(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
current_command_list_);
texture_resource = texture->GetResource();
} else {
texture_resource = nullptr;
}
bool bind_texture = current_texture_ != texture;
uint32_t texture_descriptor_index; uint32_t texture_descriptor_index;
uint64_t texture_heap_index = texture_descriptor_pool_->Request( uint64_t texture_heap_index = texture_descriptor_pool_->Request(
context_.GetSwapCurrentFenceValue(), texture_descriptor_pool_heap_index_, context_.GetSwapCurrentFenceValue(),
bind_texture ? 1 : 0, 1, texture_descriptor_index); current_texture_descriptor_heap_index_, bind_texture ? 1 : 0, 1,
texture_descriptor_index);
if (texture_heap_index == D3D12DescriptorHeapPool::kHeapIndexInvalid) { if (texture_heap_index == D3D12DescriptorHeapPool::kHeapIndexInvalid) {
return; return;
} }
if (texture_descriptor_pool_heap_index_ != texture_heap_index) { if (current_texture_descriptor_heap_index_ != texture_heap_index) {
current_texture_descriptor_heap_index_ = texture_heap_index;
bind_texture = true; bind_texture = true;
texture_descriptor_pool_heap_index_ = texture_heap_index;
ID3D12DescriptorHeap* descriptor_heaps[] = { ID3D12DescriptorHeap* descriptor_heaps[] = {
texture_descriptor_pool_->GetLastRequestHeap(), sampler_heap_}; texture_descriptor_pool_->GetLastRequestHeap(), sampler_heap_};
current_command_list_->SetDescriptorHeaps(2, descriptor_heaps); current_command_list_->SetDescriptorHeaps(2, descriptor_heaps);
} }
const D3D12Provider& provider = context_.GetD3D12Provider();
if (bind_texture) { if (bind_texture) {
current_texture_ = texture; current_texture_ = texture_resource;
D3D12_SHADER_RESOURCE_VIEW_DESC texture_view_desc; D3D12_SHADER_RESOURCE_VIEW_DESC texture_view_desc;
texture_view_desc.Format = D3D12ImmediateTexture::kFormat; texture_view_desc.Format = D3D12ImmediateTexture::kFormat;
texture_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; texture_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
texture_view_desc.Shader4ComponentMapping = if (texture_resource) {
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; texture_view_desc.Shader4ComponentMapping =
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
} else {
// No texture, solid color.
texture_view_desc.Shader4ComponentMapping =
D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1);
}
texture_view_desc.Texture2D.MostDetailedMip = 0; texture_view_desc.Texture2D.MostDetailedMip = 0;
texture_view_desc.Texture2D.MipLevels = 1; texture_view_desc.Texture2D.MipLevels = 1;
texture_view_desc.Texture2D.PlaneSlice = 0; texture_view_desc.Texture2D.PlaneSlice = 0;
texture_view_desc.Texture2D.ResourceMinLODClamp = 0.0f; texture_view_desc.Texture2D.ResourceMinLODClamp = 0.0f;
device->CreateShaderResourceView( provider.GetDevice()->CreateShaderResourceView(
texture_resource, &texture_view_desc, texture_resource, &texture_view_desc,
provider.OffsetViewDescriptor( provider.OffsetViewDescriptor(
texture_descriptor_pool_->GetLastRequestHeapCPUStart(), texture_descriptor_pool_->GetLastRequestHeapCPUStart(),
@ -634,12 +588,12 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) {
// Bind the sampler. // Bind the sampler.
SamplerIndex sampler_index; SamplerIndex sampler_index;
if (texture != nullptr) { if (texture != nullptr) {
if (texture->GetFilter() == ImmediateTextureFilter::kLinear) { if (texture->filter() == ImmediateTextureFilter::kLinear) {
sampler_index = texture->IsRepeated() ? SamplerIndex::kLinearRepeat sampler_index = texture->is_repeated() ? SamplerIndex::kLinearRepeat
: SamplerIndex::kLinearClamp; : SamplerIndex::kLinearClamp;
} else { } else {
sampler_index = texture->IsRepeated() ? SamplerIndex::kNearestRepeat sampler_index = texture->is_repeated() ? SamplerIndex::kNearestRepeat
: SamplerIndex::kNearestClamp; : SamplerIndex::kNearestClamp;
} }
} else { } else {
sampler_index = SamplerIndex::kNearestClamp; sampler_index = SamplerIndex::kNearestClamp;
@ -658,17 +612,17 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) {
UINT(RootParameter::kRestrictTextureSamples), 1, UINT(RootParameter::kRestrictTextureSamples), 1,
&restrict_texture_samples, 0); &restrict_texture_samples, 0);
// Set the primitive type and the pipeline for it. // Set the primitive type and the pipeline state for it.
D3D_PRIMITIVE_TOPOLOGY primitive_topology; D3D_PRIMITIVE_TOPOLOGY primitive_topology;
ID3D12PipelineState* pipeline; ID3D12PipelineState* pipeline_state;
switch (draw.primitive_type) { switch (draw.primitive_type) {
case ImmediatePrimitiveType::kLines: case ImmediatePrimitiveType::kLines:
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; primitive_topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
pipeline = pipeline_line_; pipeline_state = pipeline_state_line_;
break; break;
case ImmediatePrimitiveType::kTriangles: case ImmediatePrimitiveType::kTriangles:
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
pipeline = pipeline_triangle_; pipeline_state = pipeline_state_triangle_;
break; break;
default: default:
assert_unhandled_case(draw.primitive_type); assert_unhandled_case(draw.primitive_type);
@ -677,7 +631,7 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) {
if (current_primitive_topology_ != primitive_topology) { if (current_primitive_topology_ != primitive_topology) {
current_primitive_topology_ = primitive_topology; current_primitive_topology_ = primitive_topology;
current_command_list_->IASetPrimitiveTopology(primitive_topology); current_command_list_->IASetPrimitiveTopology(primitive_topology);
current_command_list_->SetPipelineState(pipeline); current_command_list_->SetPipelineState(pipeline_state);
} }
// Draw. // Draw.
@ -693,7 +647,65 @@ void D3D12ImmediateDrawer::EndDrawBatch() { batch_open_ = false; }
void D3D12ImmediateDrawer::End() { void D3D12ImmediateDrawer::End() {
assert_false(batch_open_); assert_false(batch_open_);
current_command_list_ = nullptr; if (current_command_list_) {
// Don't keep upload buffers forever if nothing was drawn in this frame.
UploadTextures();
current_command_list_ = nullptr;
}
}
void D3D12ImmediateDrawer::UploadTextures() {
assert_not_null(current_command_list_);
if (texture_uploads_pending_.empty()) {
// Called often - don't initialize anything.
return;
}
ID3D12Device* device = context_.GetD3D12Provider().GetDevice();
uint64_t current_fence_value = context_.GetSwapCurrentFenceValue();
// Copy all at once, then transition all at once (not interleaving copying and
// pipeline barriers).
std::vector<D3D12_RESOURCE_BARRIER> barriers;
barriers.reserve(texture_uploads_pending_.size());
while (!texture_uploads_pending_.empty()) {
const PendingTextureUpload& pending_upload =
texture_uploads_pending_.back();
ID3D12Resource* texture = pending_upload.texture;
D3D12_RESOURCE_DESC texture_desc = texture->GetDesc();
D3D12_TEXTURE_COPY_LOCATION location_source, location_dest;
location_source.pResource = pending_upload.buffer;
location_source.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
device->GetCopyableFootprints(&texture_desc, 0, 1, 0,
&location_source.PlacedFootprint, nullptr,
nullptr, nullptr);
location_dest.pResource = texture;
location_dest.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
location_dest.SubresourceIndex = 0;
current_command_list_->CopyTextureRegion(&location_dest, 0, 0, 0,
&location_source, nullptr);
D3D12_RESOURCE_BARRIER& barrier = barriers.emplace_back();
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = texture;
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
SubmittedTextureUpload submitted_upload;
// Transfer the reference to the texture - need to keep it until the upload
// is completed.
submitted_upload.texture = texture;
submitted_upload.buffer = pending_upload.buffer;
submitted_upload.fence_value = current_fence_value;
texture_uploads_submitted_.push_back(submitted_upload);
texture_uploads_pending_.pop_back();
}
assert_false(barriers.empty());
current_command_list_->ResourceBarrier(UINT(barriers.size()),
barriers.data());
} }
} // namespace d3d12 } // namespace d3d12

View File

@ -38,7 +38,6 @@ class D3D12ImmediateDrawer : public ImmediateDrawer {
ImmediateTextureFilter filter, ImmediateTextureFilter filter,
bool repeat, bool repeat,
const uint8_t* data) override; const uint8_t* data) override;
void UpdateTexture(ImmediateTexture* texture, const uint8_t* data) override;
void Begin(int render_target_width, int render_target_height) override; void Begin(int render_target_width, int render_target_height) override;
void BeginDrawBatch(const ImmediateDrawBatch& batch) override; void BeginDrawBatch(const ImmediateDrawBatch& batch) override;
@ -47,6 +46,8 @@ class D3D12ImmediateDrawer : public ImmediateDrawer {
void End() override; void End() override;
private: private:
void UploadTextures();
D3D12Context& context_; D3D12Context& context_;
ID3D12RootSignature* root_signature_ = nullptr; ID3D12RootSignature* root_signature_ = nullptr;
@ -59,8 +60,8 @@ class D3D12ImmediateDrawer : public ImmediateDrawer {
kCount kCount
}; };
ID3D12PipelineState* pipeline_triangle_ = nullptr; ID3D12PipelineState* pipeline_state_triangle_ = nullptr;
ID3D12PipelineState* pipeline_line_ = nullptr; ID3D12PipelineState* pipeline_state_line_ = nullptr;
enum class SamplerIndex { enum class SamplerIndex {
kNearestClamp, kNearestClamp,
@ -77,15 +78,15 @@ class D3D12ImmediateDrawer : public ImmediateDrawer {
std::unique_ptr<D3D12UploadBufferPool> vertex_buffer_pool_; std::unique_ptr<D3D12UploadBufferPool> vertex_buffer_pool_;
std::unique_ptr<D3D12DescriptorHeapPool> texture_descriptor_pool_; std::unique_ptr<D3D12DescriptorHeapPool> texture_descriptor_pool_;
uint64_t texture_descriptor_pool_heap_index_;
struct PendingTextureUpload { struct PendingTextureUpload {
ImmediateTexture* texture; ID3D12Resource* texture;
ID3D12Resource* buffer; ID3D12Resource* buffer;
}; };
std::vector<PendingTextureUpload> texture_uploads_pending_; std::vector<PendingTextureUpload> texture_uploads_pending_;
struct SubmittedTextureUpload { struct SubmittedTextureUpload {
ID3D12Resource* texture;
ID3D12Resource* buffer; ID3D12Resource* buffer;
uint64_t fence_value; uint64_t fence_value;
}; };
@ -97,7 +98,8 @@ class D3D12ImmediateDrawer : public ImmediateDrawer {
bool batch_has_index_buffer_; bool batch_has_index_buffer_;
D3D12_RECT current_scissor_; D3D12_RECT current_scissor_;
D3D_PRIMITIVE_TOPOLOGY current_primitive_topology_; D3D_PRIMITIVE_TOPOLOGY current_primitive_topology_;
ImmediateTexture* current_texture_; ID3D12Resource* current_texture_;
uint64_t current_texture_descriptor_heap_index_;
SamplerIndex current_sampler_index_; SamplerIndex current_sampler_index_;
}; };

View File

@ -20,7 +20,7 @@ namespace d3d12 {
// Align to D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT not to waste any space if // Align to D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT not to waste any space if
// it's smaller (the size of the heap backing the buffer will be aligned to // it's smaller (the size of the heap backing the buffer will be aligned to
// D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT anyway). // D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT anyway).
D3D12UploadBufferPool::D3D12UploadBufferPool(D3D12Provider& provider, D3D12UploadBufferPool::D3D12UploadBufferPool(const D3D12Provider& provider,
size_t page_size) size_t page_size)
: GraphicsUploadBufferPool(xe::align( : GraphicsUploadBufferPool(xe::align(
page_size, size_t(D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT))), page_size, size_t(D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT))),

View File

@ -19,7 +19,7 @@ namespace d3d12 {
class D3D12UploadBufferPool : public GraphicsUploadBufferPool { class D3D12UploadBufferPool : public GraphicsUploadBufferPool {
public: public:
D3D12UploadBufferPool(D3D12Provider& provider, D3D12UploadBufferPool(const D3D12Provider& provider,
size_t page_size = kDefaultPageSize); size_t page_size = kDefaultPageSize);
uint8_t* Request(uint64_t submission_index, size_t size, size_t alignment, uint8_t* Request(uint64_t submission_index, size_t size, size_t alignment,
@ -44,7 +44,7 @@ class D3D12UploadBufferPool : public GraphicsUploadBufferPool {
D3D12_GPU_VIRTUAL_ADDRESS gpu_address_; D3D12_GPU_VIRTUAL_ADDRESS gpu_address_;
}; };
D3D12Provider& provider_; const D3D12Provider& provider_;
}; };
} // namespace d3d12 } // namespace d3d12

View File

@ -23,7 +23,7 @@ const D3D12_HEAP_PROPERTIES kHeapPropertiesReadback = {
D3D12_HEAP_TYPE_READBACK}; D3D12_HEAP_TYPE_READBACK};
ID3D12RootSignature* CreateRootSignature( ID3D12RootSignature* CreateRootSignature(
D3D12Provider& provider, const D3D12_ROOT_SIGNATURE_DESC& desc) { const D3D12Provider& provider, const D3D12_ROOT_SIGNATURE_DESC& desc) {
ID3DBlob* blob; ID3DBlob* blob;
ID3DBlob* error_blob = nullptr; ID3DBlob* error_blob = nullptr;
if (FAILED(provider.SerializeRootSignature( if (FAILED(provider.SerializeRootSignature(

View File

@ -36,7 +36,7 @@ inline bool ReleaseAndNull(T& object) {
return false; return false;
}; };
ID3D12RootSignature* CreateRootSignature(D3D12Provider& provider, ID3D12RootSignature* CreateRootSignature(const D3D12Provider& provider,
const D3D12_ROOT_SIGNATURE_DESC& desc); const D3D12_ROOT_SIGNATURE_DESC& desc);
ID3D12PipelineState* CreateComputePipelineState( ID3D12PipelineState* CreateComputePipelineState(

View File

@ -96,14 +96,10 @@ class ImmediateDrawer {
public: public:
virtual ~ImmediateDrawer() = default; virtual ~ImmediateDrawer() = default;
// Creates a new texture with the given attributes and optionally updates // Creates a new texture with the given attributes and R8G8B8A8 data.
// initial data.
virtual std::unique_ptr<ImmediateTexture> CreateTexture( virtual std::unique_ptr<ImmediateTexture> CreateTexture(
uint32_t width, uint32_t height, ImmediateTextureFilter filter, uint32_t width, uint32_t height, ImmediateTextureFilter filter,
bool repeat, const uint8_t* data = nullptr) = 0; bool repeat, const uint8_t* data) = 0;
// Uploads data to the given texture, replacing the current contents.
virtual void UpdateTexture(ImmediateTexture* texture,
const uint8_t* data) = 0;
// Begins drawing in immediate mode using the given projection matrix. // Begins drawing in immediate mode using the given projection matrix.
virtual void Begin(int render_target_width, int render_target_height) = 0; virtual void Begin(int render_target_width, int render_target_height) = 0;

View File

@ -730,7 +730,7 @@ std::unique_ptr<ImmediateTexture> VulkanImmediateDrawer::CreateTexture(
} }
if (data) { if (data) {
UpdateTexture(texture.get(), data); texture->Upload(data);
} }
return std::unique_ptr<ImmediateTexture>(texture.release()); return std::unique_ptr<ImmediateTexture>(texture.release());
} }
@ -751,11 +751,6 @@ std::unique_ptr<ImmediateTexture> VulkanImmediateDrawer::WrapTexture(
return texture; return texture;
} }
void VulkanImmediateDrawer::UpdateTexture(ImmediateTexture* texture,
const uint8_t* data) {
static_cast<VulkanImmediateTexture*>(texture)->Upload(data);
}
void VulkanImmediateDrawer::Begin(int render_target_width, void VulkanImmediateDrawer::Begin(int render_target_width,
int render_target_height) { int render_target_height) {
auto device = context_->device(); auto device = context_->device();

View File

@ -39,7 +39,6 @@ class VulkanImmediateDrawer : public ImmediateDrawer {
VkSampler sampler, VkSampler sampler,
uint32_t width, uint32_t width,
uint32_t height); uint32_t height);
void UpdateTexture(ImmediateTexture* texture, const uint8_t* data) override;
void Begin(int render_target_width, int render_target_height) override; void Begin(int render_target_width, int render_target_height) override;
void BeginDrawBatch(const ImmediateDrawBatch& batch) override; void BeginDrawBatch(const ImmediateDrawBatch& batch) override;