[Vulkan] Untextured ImmediateDrawer, [D3D12] Small refactoring
This commit is contained in:
parent
36347ffedd
commit
229eb49b54
|
@ -376,7 +376,7 @@ class D3D12CommandProcessor : public CommandProcessor {
|
||||||
CommandAllocator* command_allocator_submitted_last_ = nullptr;
|
CommandAllocator* command_allocator_submitted_last_ = nullptr;
|
||||||
ID3D12GraphicsCommandList* command_list_ = nullptr;
|
ID3D12GraphicsCommandList* command_list_ = nullptr;
|
||||||
ID3D12GraphicsCommandList1* command_list_1_ = nullptr;
|
ID3D12GraphicsCommandList1* command_list_1_ = nullptr;
|
||||||
std::unique_ptr<DeferredCommandList> deferred_command_list_ = nullptr;
|
std::unique_ptr<DeferredCommandList> deferred_command_list_;
|
||||||
|
|
||||||
// Should bindless textures and samplers be used - many times faster
|
// Should bindless textures and samplers be used - many times faster
|
||||||
// UpdateBindings than bindful (that becomes a significant bottleneck with
|
// UpdateBindings than bindful (that becomes a significant bottleneck with
|
||||||
|
@ -388,14 +388,12 @@ class D3D12CommandProcessor : public CommandProcessor {
|
||||||
// targets.
|
// targets.
|
||||||
bool edram_rov_used_ = false;
|
bool edram_rov_used_ = false;
|
||||||
|
|
||||||
std::unique_ptr<ui::d3d12::D3D12UploadBufferPool> constant_buffer_pool_ =
|
std::unique_ptr<ui::d3d12::D3D12UploadBufferPool> constant_buffer_pool_;
|
||||||
nullptr;
|
|
||||||
|
|
||||||
static constexpr uint32_t kViewBindfulHeapSize = 32768;
|
static constexpr uint32_t kViewBindfulHeapSize = 32768;
|
||||||
static_assert(kViewBindfulHeapSize <=
|
static_assert(kViewBindfulHeapSize <=
|
||||||
D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1);
|
D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1);
|
||||||
std::unique_ptr<ui::d3d12::D3D12DescriptorHeapPool> view_bindful_heap_pool_ =
|
std::unique_ptr<ui::d3d12::D3D12DescriptorHeapPool> view_bindful_heap_pool_;
|
||||||
nullptr;
|
|
||||||
// Currently bound descriptor heap - updated by RequestViewBindfulDescriptors.
|
// Currently bound descriptor heap - updated by RequestViewBindfulDescriptors.
|
||||||
ID3D12DescriptorHeap* view_bindful_heap_current_;
|
ID3D12DescriptorHeap* view_bindful_heap_current_;
|
||||||
// Rationale: textures have 4 KB alignment in guest memory, and there can be
|
// Rationale: textures have 4 KB alignment in guest memory, and there can be
|
||||||
|
@ -426,7 +424,7 @@ class D3D12CommandProcessor : public CommandProcessor {
|
||||||
static constexpr uint32_t kSamplerHeapSize = 2000;
|
static constexpr uint32_t kSamplerHeapSize = 2000;
|
||||||
static_assert(kSamplerHeapSize <= D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE);
|
static_assert(kSamplerHeapSize <= D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE);
|
||||||
std::unique_ptr<ui::d3d12::D3D12DescriptorHeapPool>
|
std::unique_ptr<ui::d3d12::D3D12DescriptorHeapPool>
|
||||||
sampler_bindful_heap_pool_ = nullptr;
|
sampler_bindful_heap_pool_;
|
||||||
ID3D12DescriptorHeap* sampler_bindful_heap_current_;
|
ID3D12DescriptorHeap* sampler_bindful_heap_current_;
|
||||||
ID3D12DescriptorHeap* sampler_bindless_heap_current_ = nullptr;
|
ID3D12DescriptorHeap* sampler_bindless_heap_current_ = nullptr;
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE sampler_bindless_heap_cpu_start_;
|
D3D12_CPU_DESCRIPTOR_HANDLE sampler_bindless_heap_cpu_start_;
|
||||||
|
@ -452,15 +450,15 @@ class D3D12CommandProcessor : public CommandProcessor {
|
||||||
ID3D12RootSignature* root_signature_bindless_vs_ = nullptr;
|
ID3D12RootSignature* root_signature_bindless_vs_ = nullptr;
|
||||||
ID3D12RootSignature* root_signature_bindless_ds_ = nullptr;
|
ID3D12RootSignature* root_signature_bindless_ds_ = nullptr;
|
||||||
|
|
||||||
std::unique_ptr<SharedMemory> shared_memory_ = nullptr;
|
std::unique_ptr<SharedMemory> shared_memory_;
|
||||||
|
|
||||||
std::unique_ptr<PipelineCache> pipeline_cache_ = nullptr;
|
std::unique_ptr<PipelineCache> pipeline_cache_;
|
||||||
|
|
||||||
std::unique_ptr<TextureCache> texture_cache_ = nullptr;
|
std::unique_ptr<TextureCache> texture_cache_;
|
||||||
|
|
||||||
std::unique_ptr<RenderTargetCache> render_target_cache_ = nullptr;
|
std::unique_ptr<RenderTargetCache> render_target_cache_;
|
||||||
|
|
||||||
std::unique_ptr<PrimitiveConverter> primitive_converter_ = nullptr;
|
std::unique_ptr<PrimitiveConverter> primitive_converter_;
|
||||||
|
|
||||||
// Mip 0 contains the normal gamma ramp (256 entries), mip 1 contains the PWL
|
// Mip 0 contains the normal gamma ramp (256 entries), mip 1 contains the PWL
|
||||||
// ramp (128 entries). DXGI_FORMAT_R10G10B10A2_UNORM 1D.
|
// ramp (128 entries). DXGI_FORMAT_R10G10B10A2_UNORM 1D.
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
namespace d3d12 {
|
namespace d3d12 {
|
||||||
|
|
||||||
// Generated with `xb buildhlsl`.
|
// Generated with `xb gendxbc`.
|
||||||
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.h"
|
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/fullscreen_vs.h"
|
||||||
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h"
|
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_gamma_ps.h"
|
||||||
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h"
|
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/stretch_ps.h"
|
||||||
|
|
|
@ -56,7 +56,7 @@ namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
namespace d3d12 {
|
namespace d3d12 {
|
||||||
|
|
||||||
// Generated with `xb buildhlsl`.
|
// Generated with `xb gendxbc`.
|
||||||
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.h"
|
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_quad_hs.h"
|
||||||
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.h"
|
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/adaptive_triangle_hs.h"
|
||||||
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.h"
|
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/continuous_quad_hs.h"
|
||||||
|
|
|
@ -247,7 +247,7 @@ class PipelineCache {
|
||||||
uint32_t resolution_scale_;
|
uint32_t resolution_scale_;
|
||||||
|
|
||||||
// Reusable shader translator.
|
// Reusable shader translator.
|
||||||
std::unique_ptr<DxbcShaderTranslator> shader_translator_ = nullptr;
|
std::unique_ptr<DxbcShaderTranslator> shader_translator_;
|
||||||
|
|
||||||
// Command processor thread DXIL conversion/disassembly interfaces, if DXIL
|
// Command processor thread DXIL conversion/disassembly interfaces, if DXIL
|
||||||
// disassembly is enabled.
|
// disassembly is enabled.
|
||||||
|
@ -344,7 +344,7 @@ class PipelineCache {
|
||||||
// Manual-reset event set when the last queued pipeline state object is
|
// Manual-reset event set when the last queued pipeline state object is
|
||||||
// created and there are no more pipeline state objects to create. This is
|
// created and there are no more pipeline state objects to create. This is
|
||||||
// triggered by the thread creating the last pipeline state object.
|
// triggered by the thread creating the last pipeline state object.
|
||||||
std::unique_ptr<xe::threading::Event> creation_completion_event_ = nullptr;
|
std::unique_ptr<xe::threading::Event> creation_completion_event_;
|
||||||
// Whether setting the event on completion is queued. Protected with
|
// Whether setting the event on completion is queued. Protected with
|
||||||
// creation_request_lock_, notify_one creation_request_cond_ when set.
|
// creation_request_lock_, notify_one creation_request_cond_ when set.
|
||||||
bool creation_completion_set_event_ = false;
|
bool creation_completion_set_event_ = false;
|
||||||
|
|
|
@ -107,7 +107,7 @@ class PrimitiveConverter {
|
||||||
Memory& memory_;
|
Memory& memory_;
|
||||||
TraceWriter& trace_writer_;
|
TraceWriter& trace_writer_;
|
||||||
|
|
||||||
std::unique_ptr<ui::d3d12::D3D12UploadBufferPool> buffer_pool_ = nullptr;
|
std::unique_ptr<ui::d3d12::D3D12UploadBufferPool> buffer_pool_;
|
||||||
|
|
||||||
// Static index buffers for emulating unsupported primitive types when drawing
|
// Static index buffers for emulating unsupported primitive types when drawing
|
||||||
// without an index buffer.
|
// without an index buffer.
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
namespace d3d12 {
|
namespace d3d12 {
|
||||||
|
|
||||||
// Generated with `xb buildhlsl`.
|
// Generated with `xb gendxbc`.
|
||||||
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_32bpp_cs.h"
|
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_32bpp_cs.h"
|
||||||
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_64bpp_cs.h"
|
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_64bpp_cs.h"
|
||||||
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_7e3_cs.h"
|
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/edram_load_color_7e3_cs.h"
|
||||||
|
|
|
@ -603,7 +603,7 @@ class RenderTargetCache {
|
||||||
// For traces only.
|
// For traces only.
|
||||||
ID3D12Resource* edram_snapshot_download_buffer_ = nullptr;
|
ID3D12Resource* edram_snapshot_download_buffer_ = nullptr;
|
||||||
std::unique_ptr<ui::d3d12::D3D12UploadBufferPool>
|
std::unique_ptr<ui::d3d12::D3D12UploadBufferPool>
|
||||||
edram_snapshot_restore_pool_ = nullptr;
|
edram_snapshot_restore_pool_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace d3d12
|
} // namespace d3d12
|
||||||
|
|
|
@ -212,8 +212,7 @@ class SharedMemory {
|
||||||
std::vector<UploadRange> upload_ranges_;
|
std::vector<UploadRange> upload_ranges_;
|
||||||
void GetRangesToUpload(uint32_t request_page_first,
|
void GetRangesToUpload(uint32_t request_page_first,
|
||||||
uint32_t request_page_last);
|
uint32_t request_page_last);
|
||||||
std::unique_ptr<ui::d3d12::D3D12UploadBufferPool> upload_buffer_pool_ =
|
std::unique_ptr<ui::d3d12::D3D12UploadBufferPool> upload_buffer_pool_;
|
||||||
nullptr;
|
|
||||||
|
|
||||||
// GPU-written memory downloading for traces.
|
// GPU-written memory downloading for traces.
|
||||||
// Start page, length in pages.
|
// Start page, length in pages.
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
namespace d3d12 {
|
namespace d3d12 {
|
||||||
|
|
||||||
// Generated with `xb buildhlsl`.
|
// Generated with `xb gendxbc`.
|
||||||
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_2x_cs.h"
|
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_2x_cs.h"
|
||||||
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h"
|
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_128bpb_cs.h"
|
||||||
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_2x_cs.h"
|
#include "xenia/gpu/shaders/bytecode/d3d12_5_1/texture_load_16bpb_2x_cs.h"
|
||||||
|
|
|
@ -99,7 +99,7 @@ class D3D12Context : public GraphicsContext {
|
||||||
// kSwapCommandAllocatorCount.
|
// kSwapCommandAllocatorCount.
|
||||||
ID3D12GraphicsCommandList* swap_command_list_ = nullptr;
|
ID3D12GraphicsCommandList* swap_command_list_ = nullptr;
|
||||||
|
|
||||||
std::unique_ptr<D3D12ImmediateDrawer> immediate_drawer_ = nullptr;
|
std::unique_ptr<D3D12ImmediateDrawer> immediate_drawer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace d3d12
|
} // namespace d3d12
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
namespace d3d12 {
|
namespace d3d12 {
|
||||||
|
|
||||||
// Generated with `xb buildhlsl`.
|
// Generated with `xb gendxbc`.
|
||||||
#include "xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.h"
|
#include "xenia/ui/shaders/bytecode/d3d12_5_1/immediate_ps.h"
|
||||||
#include "xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.h"
|
#include "xenia/ui/shaders/bytecode/d3d12_5_1/immediate_vs.h"
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ bool D3D12ImmediateDrawer::Initialize() {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto& root_parameter =
|
auto& root_parameter =
|
||||||
root_parameters[size_t(RootParameter::kViewportInvSize)];
|
root_parameters[size_t(RootParameter::kViewportSizeInv)];
|
||||||
root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
|
root_parameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
|
||||||
root_parameter.Constants.ShaderRegister = 0;
|
root_parameter.Constants.ShaderRegister = 0;
|
||||||
root_parameter.Constants.RegisterSpace = 0;
|
root_parameter.Constants.RegisterSpace = 0;
|
||||||
|
@ -179,7 +179,7 @@ bool D3D12ImmediateDrawer::Initialize() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the pipelines.
|
// Create the pipeline states.
|
||||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeline_desc = {};
|
D3D12_GRAPHICS_PIPELINE_STATE_DESC pipeline_desc = {};
|
||||||
pipeline_desc.pRootSignature = root_signature_;
|
pipeline_desc.pRootSignature = root_signature_;
|
||||||
pipeline_desc.VS.pShaderBytecode = immediate_vs;
|
pipeline_desc.VS.pShaderBytecode = immediate_vs;
|
||||||
|
@ -192,10 +192,13 @@ bool D3D12ImmediateDrawer::Initialize() {
|
||||||
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;
|
||||||
pipeline_blend_desc.BlendOp = D3D12_BLEND_OP_ADD;
|
pipeline_blend_desc.BlendOp = D3D12_BLEND_OP_ADD;
|
||||||
pipeline_blend_desc.SrcBlendAlpha = D3D12_BLEND_SRC_ALPHA;
|
// Don't change alpha (always 1).
|
||||||
pipeline_blend_desc.DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
|
pipeline_blend_desc.SrcBlendAlpha = D3D12_BLEND_ZERO;
|
||||||
|
pipeline_blend_desc.DestBlendAlpha = D3D12_BLEND_ONE;
|
||||||
pipeline_blend_desc.BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
pipeline_blend_desc.BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
||||||
pipeline_blend_desc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
pipeline_blend_desc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_RED |
|
||||||
|
D3D12_COLOR_WRITE_ENABLE_GREEN |
|
||||||
|
D3D12_COLOR_WRITE_ENABLE_BLUE;
|
||||||
pipeline_desc.SampleMask = UINT_MAX;
|
pipeline_desc.SampleMask = UINT_MAX;
|
||||||
pipeline_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
pipeline_desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
||||||
pipeline_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
|
pipeline_desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
|
||||||
|
@ -295,6 +298,7 @@ bool D3D12ImmediateDrawer::Initialize() {
|
||||||
|
|
||||||
// Reset the current state.
|
// Reset the current state.
|
||||||
current_command_list_ = nullptr;
|
current_command_list_ = nullptr;
|
||||||
|
batch_open_ = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -415,6 +419,9 @@ void D3D12ImmediateDrawer::UpdateTexture(ImmediateTexture* texture,
|
||||||
|
|
||||||
void D3D12ImmediateDrawer::Begin(int render_target_width,
|
void D3D12ImmediateDrawer::Begin(int render_target_width,
|
||||||
int render_target_height) {
|
int render_target_height) {
|
||||||
|
assert_null(current_command_list_);
|
||||||
|
assert_false(batch_open_);
|
||||||
|
|
||||||
auto device = context_.GetD3D12Provider().GetDevice();
|
auto device = context_.GetD3D12Provider().GetDevice();
|
||||||
|
|
||||||
// Use the compositing command list.
|
// Use the compositing command list.
|
||||||
|
@ -485,7 +492,7 @@ void D3D12ImmediateDrawer::Begin(int render_target_width,
|
||||||
viewport_inv_size[0] = 1.0f / viewport.Width;
|
viewport_inv_size[0] = 1.0f / viewport.Width;
|
||||||
viewport_inv_size[1] = 1.0f / viewport.Height;
|
viewport_inv_size[1] = 1.0f / viewport.Height;
|
||||||
current_command_list_->SetGraphicsRoot32BitConstants(
|
current_command_list_->SetGraphicsRoot32BitConstants(
|
||||||
UINT(RootParameter::kViewportInvSize), 2, viewport_inv_size, 0);
|
UINT(RootParameter::kViewportSizeInv), 2, viewport_inv_size, 0);
|
||||||
|
|
||||||
current_primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
current_primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
||||||
current_texture_ = nullptr;
|
current_texture_ = nullptr;
|
||||||
|
@ -493,21 +500,18 @@ void D3D12ImmediateDrawer::Begin(int render_target_width,
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D12ImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) {
|
void D3D12ImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) {
|
||||||
|
assert_false(batch_open_);
|
||||||
assert_not_null(current_command_list_);
|
assert_not_null(current_command_list_);
|
||||||
if (current_command_list_ == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint64_t current_fence_value = context_.GetSwapCurrentFenceValue();
|
|
||||||
|
|
||||||
batch_open_ = false;
|
uint64_t current_fence_value = context_.GetSwapCurrentFenceValue();
|
||||||
|
|
||||||
// Bind the vertices.
|
// Bind the vertices.
|
||||||
D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view;
|
D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view;
|
||||||
vertex_buffer_view.StrideInBytes = UINT(sizeof(ImmediateVertex));
|
vertex_buffer_view.StrideInBytes = UINT(sizeof(ImmediateVertex));
|
||||||
vertex_buffer_view.SizeInBytes =
|
vertex_buffer_view.SizeInBytes =
|
||||||
batch.vertex_count * uint32_t(sizeof(ImmediateVertex));
|
UINT(sizeof(ImmediateVertex)) * batch.vertex_count;
|
||||||
void* vertex_buffer_mapping = vertex_buffer_pool_->Request(
|
void* vertex_buffer_mapping = vertex_buffer_pool_->Request(
|
||||||
current_fence_value, vertex_buffer_view.SizeInBytes, sizeof(uint32_t),
|
current_fence_value, vertex_buffer_view.SizeInBytes, sizeof(float),
|
||||||
nullptr, nullptr, &vertex_buffer_view.BufferLocation);
|
nullptr, nullptr, &vertex_buffer_view.BufferLocation);
|
||||||
if (vertex_buffer_mapping == nullptr) {
|
if (vertex_buffer_mapping == nullptr) {
|
||||||
XELOGE("Failed to get a buffer for {} vertices in the immediate drawer",
|
XELOGE("Failed to get a buffer for {} vertices in the immediate drawer",
|
||||||
|
@ -522,7 +526,7 @@ void D3D12ImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) {
|
||||||
batch_has_index_buffer_ = batch.indices != nullptr;
|
batch_has_index_buffer_ = batch.indices != nullptr;
|
||||||
if (batch_has_index_buffer_) {
|
if (batch_has_index_buffer_) {
|
||||||
D3D12_INDEX_BUFFER_VIEW index_buffer_view;
|
D3D12_INDEX_BUFFER_VIEW index_buffer_view;
|
||||||
index_buffer_view.SizeInBytes = batch.index_count * sizeof(uint16_t);
|
index_buffer_view.SizeInBytes = UINT(sizeof(uint16_t)) * batch.index_count;
|
||||||
index_buffer_view.Format = DXGI_FORMAT_R16_UINT;
|
index_buffer_view.Format = DXGI_FORMAT_R16_UINT;
|
||||||
void* index_buffer_mapping = vertex_buffer_pool_->Request(
|
void* index_buffer_mapping = vertex_buffer_pool_->Request(
|
||||||
current_fence_value, index_buffer_view.SizeInBytes, sizeof(uint16_t),
|
current_fence_value, index_buffer_view.SizeInBytes, sizeof(uint16_t),
|
||||||
|
@ -541,11 +545,6 @@ void D3D12ImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) {
|
void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) {
|
||||||
assert_not_null(current_command_list_);
|
|
||||||
if (current_command_list_ == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!batch_open_) {
|
if (!batch_open_) {
|
||||||
// Could be an error while obtaining the vertex and index buffers.
|
// Could be an error while obtaining the vertex and index buffers.
|
||||||
return;
|
return;
|
||||||
|
@ -678,7 +677,10 @@ void D3D12ImmediateDrawer::Draw(const ImmediateDraw& draw) {
|
||||||
|
|
||||||
void D3D12ImmediateDrawer::EndDrawBatch() { batch_open_ = false; }
|
void D3D12ImmediateDrawer::EndDrawBatch() { batch_open_ = false; }
|
||||||
|
|
||||||
void D3D12ImmediateDrawer::End() { current_command_list_ = nullptr; }
|
void D3D12ImmediateDrawer::End() {
|
||||||
|
assert_false(batch_open_);
|
||||||
|
current_command_list_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace d3d12
|
} // namespace d3d12
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|
|
@ -54,7 +54,7 @@ class D3D12ImmediateDrawer : public ImmediateDrawer {
|
||||||
kRestrictTextureSamples,
|
kRestrictTextureSamples,
|
||||||
kTexture,
|
kTexture,
|
||||||
kSampler,
|
kSampler,
|
||||||
kViewportInvSize,
|
kViewportSizeInv,
|
||||||
|
|
||||||
kCount
|
kCount
|
||||||
};
|
};
|
||||||
|
@ -75,8 +75,8 @@ class D3D12ImmediateDrawer : public ImmediateDrawer {
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE sampler_heap_cpu_start_;
|
D3D12_CPU_DESCRIPTOR_HANDLE sampler_heap_cpu_start_;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE sampler_heap_gpu_start_;
|
D3D12_GPU_DESCRIPTOR_HANDLE sampler_heap_gpu_start_;
|
||||||
|
|
||||||
std::unique_ptr<D3D12UploadBufferPool> vertex_buffer_pool_ = nullptr;
|
std::unique_ptr<D3D12UploadBufferPool> vertex_buffer_pool_;
|
||||||
std::unique_ptr<D3D12DescriptorHeapPool> texture_descriptor_pool_ = nullptr;
|
std::unique_ptr<D3D12DescriptorHeapPool> texture_descriptor_pool_;
|
||||||
uint64_t texture_descriptor_pool_heap_index_;
|
uint64_t texture_descriptor_pool_heap_index_;
|
||||||
|
|
||||||
struct PendingTextureUpload {
|
struct PendingTextureUpload {
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
// generated from `xb genspirv`
|
||||||
|
// source: immediate.frag
|
||||||
|
const uint8_t immediate_frag[] = {
|
||||||
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00,
|
||||||
|
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x09, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x78, 0x65, 0x5F, 0x66, 0x72, 0x61, 0x67, 0x5F, 0x63, 0x6F, 0x6C, 0x6F,
|
||||||
|
0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||||
|
0x78, 0x65, 0x5F, 0x76, 0x61, 0x72, 0x5F, 0x63, 0x6F, 0x6C, 0x6F, 0x72,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x78, 0x65, 0x5F, 0x76, 0x61, 0x72, 0x5F, 0x74, 0x65, 0x78, 0x63, 0x6F,
|
||||||
|
0x6F, 0x72, 0x64, 0x00, 0x47, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
|
||||||
|
0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x0B, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||||
|
0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x07, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||||
|
0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x0B, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x0C, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
|
};
|
Binary file not shown.
|
@ -0,0 +1,38 @@
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.0
|
||||||
|
; Generator: Khronos Glslang Reference Front End; 10
|
||||||
|
; Bound: 16
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
%1 = OpExtInstImport "GLSL.std.450"
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %main "main" %xe_frag_color %xe_var_color %xe_var_texcoord
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
OpSource ESSL 310
|
||||||
|
OpName %main "main"
|
||||||
|
OpName %xe_frag_color "xe_frag_color"
|
||||||
|
OpName %xe_var_color "xe_var_color"
|
||||||
|
OpName %xe_var_texcoord "xe_var_texcoord"
|
||||||
|
OpDecorate %xe_frag_color RelaxedPrecision
|
||||||
|
OpDecorate %xe_frag_color Location 0
|
||||||
|
OpDecorate %xe_var_color RelaxedPrecision
|
||||||
|
OpDecorate %xe_var_color Location 1
|
||||||
|
OpDecorate %12 RelaxedPrecision
|
||||||
|
OpDecorate %xe_var_texcoord Location 0
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%3 = OpTypeFunction %void
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%v4float = OpTypeVector %float 4
|
||||||
|
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||||
|
%xe_frag_color = OpVariable %_ptr_Output_v4float Output
|
||||||
|
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||||
|
%xe_var_color = OpVariable %_ptr_Input_v4float Input
|
||||||
|
%v2float = OpTypeVector %float 2
|
||||||
|
%_ptr_Input_v2float = OpTypePointer Input %v2float
|
||||||
|
%xe_var_texcoord = OpVariable %_ptr_Input_v2float Input
|
||||||
|
%main = OpFunction %void None %3
|
||||||
|
%5 = OpLabel
|
||||||
|
%12 = OpLoad %v4float %xe_var_color
|
||||||
|
OpStore %xe_frag_color %12
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,116 @@
|
||||||
|
// generated from `xb genspirv`
|
||||||
|
// source: immediate.vert
|
||||||
|
const uint8_t immediate_vert[] = {
|
||||||
|
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x08, 0x00,
|
||||||
|
0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x4C, 0x53, 0x4C, 0x2E, 0x73, 0x74, 0x64, 0x2E, 0x34, 0x35, 0x30,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x09, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x69, 0x6E,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x78, 0x65, 0x5F, 0x76, 0x61, 0x72, 0x5F, 0x74, 0x65, 0x78, 0x63, 0x6F,
|
||||||
|
0x6F, 0x72, 0x64, 0x00, 0x05, 0x00, 0x07, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||||
|
0x78, 0x65, 0x5F, 0x61, 0x74, 0x74, 0x72, 0x5F, 0x74, 0x65, 0x78, 0x63,
|
||||||
|
0x6F, 0x6F, 0x72, 0x64, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x76, 0x61, 0x72, 0x5F, 0x63,
|
||||||
|
0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x61, 0x74, 0x74, 0x72, 0x5F,
|
||||||
|
0x63, 0x6F, 0x6C, 0x6F, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00,
|
||||||
|
0x13, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50, 0x65, 0x72, 0x56, 0x65,
|
||||||
|
0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00,
|
||||||
|
0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50,
|
||||||
|
0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x00, 0x06, 0x00, 0x07, 0x00,
|
||||||
|
0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x67, 0x6C, 0x5F, 0x50,
|
||||||
|
0x6F, 0x69, 0x6E, 0x74, 0x53, 0x69, 0x7A, 0x65, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x03, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x07, 0x00, 0x18, 0x00, 0x00, 0x00, 0x78, 0x65, 0x5F, 0x61,
|
||||||
|
0x74, 0x74, 0x72, 0x5F, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69, 0x6F, 0x6E,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x1A, 0x00, 0x00, 0x00,
|
||||||
|
0x58, 0x65, 0x50, 0x75, 0x73, 0x68, 0x43, 0x6F, 0x6E, 0x73, 0x74, 0x61,
|
||||||
|
0x6E, 0x74, 0x73, 0x00, 0x06, 0x00, 0x08, 0x00, 0x1A, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6F, 0x72, 0x74,
|
||||||
|
0x5F, 0x73, 0x69, 0x7A, 0x65, 0x5F, 0x69, 0x6E, 0x76, 0x00, 0x00, 0x00,
|
||||||
|
0x05, 0x00, 0x03, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||||
|
0x1E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x0F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x03, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x48, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
|
||||||
|
0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x48, 0x00, 0x05, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
|
||||||
|
0x1A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||||
|
0x3B, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||||
|
0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||||
|
0x0A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x04, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00,
|
||||||
|
0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x0D, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x00,
|
||||||
|
0x13, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x20, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0x13, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||||
|
0x15, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
|
||||||
|
0x16, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x2B, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x3B, 0x00, 0x04, 0x00, 0x0A, 0x00, 0x00, 0x00,
|
||||||
|
0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x03, 0x00,
|
||||||
|
0x1A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||||
|
0x1B, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00,
|
||||||
|
0x3B, 0x00, 0x04, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
|
||||||
|
0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1D, 0x00, 0x00, 0x00,
|
||||||
|
0x09, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x04, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
|
||||||
|
0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x80, 0x3F, 0x2B, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x05, 0x00,
|
||||||
|
0x07, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||||
|
0xF8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00,
|
||||||
|
0x07, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
|
||||||
|
0x3E, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
|
||||||
|
0x3D, 0x00, 0x04, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||||
|
0x11, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x03, 0x00, 0x0F, 0x00, 0x00, 0x00,
|
||||||
|
0x12, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||||
|
0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
|
||||||
|
0x1D, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
|
||||||
|
0x17, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||||
|
0x1F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
|
||||||
|
0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
|
||||||
|
0x1F, 0x00, 0x00, 0x00, 0x8E, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||||
|
0x22, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
|
||||||
|
0x83, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
|
||||||
|
0x22, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||||
|
0x28, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x50, 0x00, 0x07, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
|
||||||
|
0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
|
||||||
|
0x23, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0E, 0x00, 0x00, 0x00,
|
||||||
|
0x2A, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||||
|
0x3E, 0x00, 0x03, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
|
||||||
|
0xFD, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00,
|
||||||
|
};
|
Binary file not shown.
|
@ -0,0 +1,82 @@
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.0
|
||||||
|
; Generator: Khronos Glslang Reference Front End; 10
|
||||||
|
; Bound: 44
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
%1 = OpExtInstImport "GLSL.std.450"
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Vertex %main "main" %xe_var_texcoord %xe_attr_texcoord %xe_var_color %xe_attr_color %_ %xe_attr_position
|
||||||
|
OpSource ESSL 310
|
||||||
|
OpName %main "main"
|
||||||
|
OpName %xe_var_texcoord "xe_var_texcoord"
|
||||||
|
OpName %xe_attr_texcoord "xe_attr_texcoord"
|
||||||
|
OpName %xe_var_color "xe_var_color"
|
||||||
|
OpName %xe_attr_color "xe_attr_color"
|
||||||
|
OpName %gl_PerVertex "gl_PerVertex"
|
||||||
|
OpMemberName %gl_PerVertex 0 "gl_Position"
|
||||||
|
OpMemberName %gl_PerVertex 1 "gl_PointSize"
|
||||||
|
OpName %_ ""
|
||||||
|
OpName %xe_attr_position "xe_attr_position"
|
||||||
|
OpName %XePushConstants "XePushConstants"
|
||||||
|
OpMemberName %XePushConstants 0 "viewport_size_inv"
|
||||||
|
OpName %__0 ""
|
||||||
|
OpDecorate %xe_var_texcoord Location 0
|
||||||
|
OpDecorate %xe_attr_texcoord Location 1
|
||||||
|
OpDecorate %xe_var_color RelaxedPrecision
|
||||||
|
OpDecorate %xe_var_color Location 1
|
||||||
|
OpDecorate %xe_attr_color RelaxedPrecision
|
||||||
|
OpDecorate %xe_attr_color Location 2
|
||||||
|
OpDecorate %18 RelaxedPrecision
|
||||||
|
OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
|
||||||
|
OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
|
||||||
|
OpDecorate %gl_PerVertex Block
|
||||||
|
OpDecorate %xe_attr_position Location 0
|
||||||
|
OpMemberDecorate %XePushConstants 0 Offset 0
|
||||||
|
OpDecorate %XePushConstants Block
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%3 = OpTypeFunction %void
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%v2float = OpTypeVector %float 2
|
||||||
|
%_ptr_Output_v2float = OpTypePointer Output %v2float
|
||||||
|
%xe_var_texcoord = OpVariable %_ptr_Output_v2float Output
|
||||||
|
%_ptr_Input_v2float = OpTypePointer Input %v2float
|
||||||
|
%xe_attr_texcoord = OpVariable %_ptr_Input_v2float Input
|
||||||
|
%v4float = OpTypeVector %float 4
|
||||||
|
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||||
|
%xe_var_color = OpVariable %_ptr_Output_v4float Output
|
||||||
|
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||||
|
%xe_attr_color = OpVariable %_ptr_Input_v4float Input
|
||||||
|
%gl_PerVertex = OpTypeStruct %v4float %float
|
||||||
|
%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
|
||||||
|
%_ = OpVariable %_ptr_Output_gl_PerVertex Output
|
||||||
|
%int = OpTypeInt 32 1
|
||||||
|
%int_0 = OpConstant %int 0
|
||||||
|
%xe_attr_position = OpVariable %_ptr_Input_v2float Input
|
||||||
|
%XePushConstants = OpTypeStruct %v2float
|
||||||
|
%_ptr_PushConstant_XePushConstants = OpTypePointer PushConstant %XePushConstants
|
||||||
|
%__0 = OpVariable %_ptr_PushConstant_XePushConstants PushConstant
|
||||||
|
%_ptr_PushConstant_v2float = OpTypePointer PushConstant %v2float
|
||||||
|
%float_2 = OpConstant %float 2
|
||||||
|
%float_1 = OpConstant %float 1
|
||||||
|
%float_0 = OpConstant %float 0
|
||||||
|
%43 = OpConstantComposite %v2float %float_1 %float_1
|
||||||
|
%main = OpFunction %void None %3
|
||||||
|
%5 = OpLabel
|
||||||
|
%12 = OpLoad %v2float %xe_attr_texcoord
|
||||||
|
OpStore %xe_var_texcoord %12
|
||||||
|
%18 = OpLoad %v4float %xe_attr_color
|
||||||
|
OpStore %xe_var_color %18
|
||||||
|
%25 = OpLoad %v2float %xe_attr_position
|
||||||
|
%30 = OpAccessChain %_ptr_PushConstant_v2float %__0 %int_0
|
||||||
|
%31 = OpLoad %v2float %30
|
||||||
|
%32 = OpFMul %v2float %25 %31
|
||||||
|
%34 = OpVectorTimesScalar %v2float %32 %float_2
|
||||||
|
%37 = OpFSub %v2float %34 %43
|
||||||
|
%39 = OpCompositeExtract %float %37 0
|
||||||
|
%40 = OpCompositeExtract %float %37 1
|
||||||
|
%41 = OpCompositeConstruct %v4float %39 %40 %float_0 %float_1
|
||||||
|
%42 = OpAccessChain %_ptr_Output_v4float %_ %int_0
|
||||||
|
OpStore %42 %41
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,11 @@
|
||||||
|
#version 310 es
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 xe_var_texcoord;
|
||||||
|
layout(location = 1) in lowp vec4 xe_var_color;
|
||||||
|
|
||||||
|
layout(location = 0) out lowp vec4 xe_frag_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
xe_frag_color = xe_var_color;
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#version 310 es
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
layout(push_constant) uniform XePushConstants {
|
||||||
|
layout(offset = 0) vec2 viewport_size_inv;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 xe_attr_position;
|
||||||
|
layout(location = 1) in vec2 xe_attr_texcoord;
|
||||||
|
layout(location = 2) in lowp vec4 xe_attr_color;
|
||||||
|
|
||||||
|
layout(location = 0) out vec2 xe_var_texcoord;
|
||||||
|
layout(location = 1) out lowp vec4 xe_var_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
xe_var_texcoord = xe_attr_texcoord;
|
||||||
|
xe_var_color = xe_attr_color;
|
||||||
|
gl_Position = vec4(xe_attr_position * viewport_size_inv * 2.0 - 1.0, 0.0,
|
||||||
|
1.0);
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
float2 xe_viewport_inv_size : register(b0);
|
float2 xe_viewport_size_inv : register(b0);
|
||||||
|
|
||||||
struct XeVertexShaderInput {
|
struct XeVertexShaderInput {
|
||||||
float2 position : POSITION;
|
float2 position : POSITION;
|
||||||
|
@ -14,10 +14,10 @@ struct XeVertexShaderOutput {
|
||||||
|
|
||||||
XeVertexShaderOutput main(XeVertexShaderInput input) {
|
XeVertexShaderOutput main(XeVertexShaderInput input) {
|
||||||
XeVertexShaderOutput output;
|
XeVertexShaderOutput output;
|
||||||
output.position = float4(
|
|
||||||
input.position * xe_viewport_inv_size * float2(2.0, -2.0) +
|
|
||||||
float2(-1.0, 1.0), 0.0, 1.0);
|
|
||||||
output.texcoord = input.texcoord;
|
output.texcoord = input.texcoord;
|
||||||
output.color = input.color;
|
output.color = input.color;
|
||||||
|
output.position = float4(
|
||||||
|
input.position * xe_viewport_size_inv * float2(2.0, -2.0) +
|
||||||
|
float2(-1.0, 1.0), 0.0, 1.0);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,3 +14,24 @@ project("xenia-ui-vulkan")
|
||||||
files({
|
files({
|
||||||
"../shaders/bytecode/vulkan_spirv/*.h",
|
"../shaders/bytecode/vulkan_spirv/*.h",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
group("demos")
|
||||||
|
project("xenia-ui-window-vulkan-demo")
|
||||||
|
uuid("97598f13-3177-454c-8e58-c59e2b6ede27")
|
||||||
|
kind("WindowedApp")
|
||||||
|
language("C++")
|
||||||
|
links({
|
||||||
|
"fmt",
|
||||||
|
"imgui",
|
||||||
|
"xenia-base",
|
||||||
|
"xenia-ui",
|
||||||
|
"xenia-ui-vulkan",
|
||||||
|
})
|
||||||
|
files({
|
||||||
|
"../window_demo.cc",
|
||||||
|
"vulkan_window_demo.cc",
|
||||||
|
project_root.."/src/xenia/base/main_"..platform_suffix..".cc",
|
||||||
|
})
|
||||||
|
resincludedirs({
|
||||||
|
project_root,
|
||||||
|
})
|
||||||
|
|
|
@ -35,6 +35,8 @@ namespace vulkan {
|
||||||
VulkanContext::VulkanContext(VulkanProvider* provider, Window* target_window)
|
VulkanContext::VulkanContext(VulkanProvider* provider, Window* target_window)
|
||||||
: GraphicsContext(provider, target_window) {}
|
: GraphicsContext(provider, target_window) {}
|
||||||
|
|
||||||
|
VulkanContext::~VulkanContext() { Shutdown(); }
|
||||||
|
|
||||||
bool VulkanContext::Initialize() {
|
bool VulkanContext::Initialize() {
|
||||||
context_lost_ = false;
|
context_lost_ = false;
|
||||||
|
|
||||||
|
@ -110,7 +112,10 @@ bool VulkanContext::Initialize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
immediate_drawer_ = std::make_unique<VulkanImmediateDrawer>(*this);
|
immediate_drawer_ = std::make_unique<VulkanImmediateDrawer>(*this);
|
||||||
// TODO(Triang3l): Initialize the immediate drawer.
|
if (!immediate_drawer_->Initialize()) {
|
||||||
|
Shutdown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
swap_swapchain_or_surface_recreation_needed_ = true;
|
swap_swapchain_or_surface_recreation_needed_ = true;
|
||||||
|
|
||||||
|
@ -124,6 +129,8 @@ void VulkanContext::Shutdown() {
|
||||||
|
|
||||||
AwaitAllSwapSubmissionsCompletion();
|
AwaitAllSwapSubmissionsCompletion();
|
||||||
|
|
||||||
|
immediate_drawer_.reset();
|
||||||
|
|
||||||
const VulkanProvider& provider = GetVulkanProvider();
|
const VulkanProvider& provider = GetVulkanProvider();
|
||||||
const VulkanProvider::InstanceFunctions& ifn = provider.ifn();
|
const VulkanProvider::InstanceFunctions& ifn = provider.ifn();
|
||||||
VkInstance instance = provider.instance();
|
VkInstance instance = provider.instance();
|
||||||
|
|
|
@ -24,6 +24,8 @@ namespace vulkan {
|
||||||
|
|
||||||
class VulkanContext : public GraphicsContext {
|
class VulkanContext : public GraphicsContext {
|
||||||
public:
|
public:
|
||||||
|
~VulkanContext() override;
|
||||||
|
|
||||||
ImmediateDrawer* immediate_drawer() override;
|
ImmediateDrawer* immediate_drawer() override;
|
||||||
|
|
||||||
bool WasLost() override;
|
bool WasLost() override;
|
||||||
|
@ -43,6 +45,15 @@ class VulkanContext : public GraphicsContext {
|
||||||
return swap_submissions_[swap_submission_current_ % kSwapchainMaxImageCount]
|
return swap_submissions_[swap_submission_current_ % kSwapchainMaxImageCount]
|
||||||
.command_buffer;
|
.command_buffer;
|
||||||
}
|
}
|
||||||
|
uint64_t swap_submission_current() const { return swap_submission_current_; }
|
||||||
|
uint64_t swap_submission_completed() const {
|
||||||
|
return swap_submission_completed_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VkSurfaceFormatKHR& swap_surface_format() const {
|
||||||
|
return swap_surface_format_;
|
||||||
|
}
|
||||||
|
VkRenderPass swap_render_pass() const { return swap_render_pass_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class VulkanProvider;
|
friend class VulkanProvider;
|
||||||
|
|
|
@ -9,12 +9,22 @@
|
||||||
|
|
||||||
#include "xenia/ui/vulkan/vulkan_immediate_drawer.h"
|
#include "xenia/ui/vulkan/vulkan_immediate_drawer.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "xenia/base/assert.h"
|
||||||
|
#include "xenia/base/logging.h"
|
||||||
|
#include "xenia/base/math.h"
|
||||||
#include "xenia/ui/vulkan/vulkan_context.h"
|
#include "xenia/ui/vulkan/vulkan_context.h"
|
||||||
|
#include "xenia/ui/vulkan/vulkan_util.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
namespace vulkan {
|
namespace vulkan {
|
||||||
|
|
||||||
|
// Generated with `xb genspirv`.
|
||||||
|
#include "xenia/ui/shaders/bytecode/vulkan_spirv/immediate_frag.h"
|
||||||
|
#include "xenia/ui/shaders/bytecode/vulkan_spirv/immediate_vert.h"
|
||||||
|
|
||||||
class VulkanImmediateTexture : public ImmediateTexture {
|
class VulkanImmediateTexture : public ImmediateTexture {
|
||||||
public:
|
public:
|
||||||
VulkanImmediateTexture(uint32_t width, uint32_t height)
|
VulkanImmediateTexture(uint32_t width, uint32_t height)
|
||||||
|
@ -24,6 +34,59 @@ class VulkanImmediateTexture : public ImmediateTexture {
|
||||||
VulkanImmediateDrawer::VulkanImmediateDrawer(VulkanContext& graphics_context)
|
VulkanImmediateDrawer::VulkanImmediateDrawer(VulkanContext& graphics_context)
|
||||||
: ImmediateDrawer(&graphics_context), context_(graphics_context) {}
|
: ImmediateDrawer(&graphics_context), context_(graphics_context) {}
|
||||||
|
|
||||||
|
VulkanImmediateDrawer::~VulkanImmediateDrawer() { Shutdown(); }
|
||||||
|
|
||||||
|
bool VulkanImmediateDrawer::Initialize() {
|
||||||
|
const VulkanProvider& provider = context_.GetVulkanProvider();
|
||||||
|
const VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||||
|
VkDevice device = provider.device();
|
||||||
|
|
||||||
|
VkPushConstantRange push_constant_ranges[1];
|
||||||
|
push_constant_ranges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
push_constant_ranges[0].offset = offsetof(PushConstants, vertex);
|
||||||
|
push_constant_ranges[0].size = sizeof(PushConstants::Vertex);
|
||||||
|
VkPipelineLayoutCreateInfo pipeline_layout_create_info;
|
||||||
|
pipeline_layout_create_info.sType =
|
||||||
|
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
|
pipeline_layout_create_info.pNext = nullptr;
|
||||||
|
pipeline_layout_create_info.flags = 0;
|
||||||
|
pipeline_layout_create_info.setLayoutCount = 0;
|
||||||
|
pipeline_layout_create_info.pSetLayouts = nullptr;
|
||||||
|
pipeline_layout_create_info.pushConstantRangeCount =
|
||||||
|
uint32_t(xe::countof(push_constant_ranges));
|
||||||
|
pipeline_layout_create_info.pPushConstantRanges = push_constant_ranges;
|
||||||
|
if (dfn.vkCreatePipelineLayout(device, &pipeline_layout_create_info, nullptr,
|
||||||
|
&pipeline_layout_) != VK_SUCCESS) {
|
||||||
|
XELOGE("Failed to create the immediate drawer Vulkan pipeline layout");
|
||||||
|
Shutdown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex_buffer_pool_ = std::make_unique<VulkanUploadBufferPool>(
|
||||||
|
provider,
|
||||||
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Reset the current state.
|
||||||
|
current_command_buffer_ = VK_NULL_HANDLE;
|
||||||
|
batch_open_ = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanImmediateDrawer::Shutdown() {
|
||||||
|
const VulkanProvider& provider = context_.GetVulkanProvider();
|
||||||
|
const VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||||
|
VkDevice device = provider.device();
|
||||||
|
|
||||||
|
util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_line_);
|
||||||
|
util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_triangle_);
|
||||||
|
|
||||||
|
vertex_buffer_pool_.reset();
|
||||||
|
|
||||||
|
util::DestroyAndNullHandle(dfn.vkDestroyPipelineLayout, device,
|
||||||
|
pipeline_layout_);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<ImmediateTexture> VulkanImmediateDrawer::CreateTexture(
|
std::unique_ptr<ImmediateTexture> VulkanImmediateDrawer::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) {
|
||||||
|
@ -35,15 +98,355 @@ void VulkanImmediateDrawer::UpdateTexture(ImmediateTexture* texture,
|
||||||
const uint8_t* data) {}
|
const uint8_t* data) {}
|
||||||
|
|
||||||
void VulkanImmediateDrawer::Begin(int render_target_width,
|
void VulkanImmediateDrawer::Begin(int render_target_width,
|
||||||
int render_target_height) {}
|
int render_target_height) {
|
||||||
|
assert_true(current_command_buffer_ == VK_NULL_HANDLE);
|
||||||
|
assert_false(batch_open_);
|
||||||
|
|
||||||
void VulkanImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) {}
|
if (!EnsurePipelinesCreated()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void VulkanImmediateDrawer::Draw(const ImmediateDraw& draw) {}
|
current_command_buffer_ = context_.GetSwapCommandBuffer();
|
||||||
|
|
||||||
void VulkanImmediateDrawer::EndDrawBatch() {}
|
uint64_t submission_completed = context_.swap_submission_completed();
|
||||||
|
vertex_buffer_pool_->Reclaim(submission_completed);
|
||||||
|
|
||||||
void VulkanImmediateDrawer::End() {}
|
const VulkanProvider::DeviceFunctions& dfn =
|
||||||
|
context_.GetVulkanProvider().dfn();
|
||||||
|
|
||||||
|
current_render_target_extent_.width = uint32_t(render_target_width);
|
||||||
|
current_render_target_extent_.height = uint32_t(render_target_height);
|
||||||
|
VkViewport viewport;
|
||||||
|
viewport.x = 0.0f;
|
||||||
|
viewport.y = 0.0f;
|
||||||
|
viewport.width = float(render_target_width);
|
||||||
|
viewport.height = float(render_target_height);
|
||||||
|
viewport.minDepth = 0.0f;
|
||||||
|
viewport.maxDepth = 1.0f;
|
||||||
|
dfn.vkCmdSetViewport(current_command_buffer_, 0, 1, &viewport);
|
||||||
|
PushConstants::Vertex push_constants_vertex;
|
||||||
|
push_constants_vertex.viewport_size_inv[0] = 1.0f / viewport.width;
|
||||||
|
push_constants_vertex.viewport_size_inv[1] = 1.0f / viewport.height;
|
||||||
|
dfn.vkCmdPushConstants(current_command_buffer_, pipeline_layout_,
|
||||||
|
VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
offsetof(PushConstants, vertex),
|
||||||
|
sizeof(PushConstants::Vertex), &push_constants_vertex);
|
||||||
|
|
||||||
|
current_pipeline_ = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) {
|
||||||
|
assert_false(batch_open_);
|
||||||
|
if (current_command_buffer_ == VK_NULL_HANDLE) {
|
||||||
|
// No surface, or failed to create the pipelines.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t submission_current = context_.swap_submission_current();
|
||||||
|
const VulkanProvider::DeviceFunctions& dfn =
|
||||||
|
context_.GetVulkanProvider().dfn();
|
||||||
|
|
||||||
|
// Bind the vertices.
|
||||||
|
size_t vertex_buffer_size = sizeof(ImmediateVertex) * batch.vertex_count;
|
||||||
|
VkBuffer vertex_buffer;
|
||||||
|
VkDeviceSize vertex_buffer_offset;
|
||||||
|
void* vertex_buffer_mapping = vertex_buffer_pool_->Request(
|
||||||
|
submission_current, vertex_buffer_size, sizeof(float), vertex_buffer,
|
||||||
|
vertex_buffer_offset);
|
||||||
|
if (!vertex_buffer_mapping) {
|
||||||
|
XELOGE("Failed to get a buffer for {} vertices in the immediate drawer",
|
||||||
|
batch.vertex_count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::memcpy(vertex_buffer_mapping, batch.vertices, vertex_buffer_size);
|
||||||
|
dfn.vkCmdBindVertexBuffers(current_command_buffer_, 0, 1, &vertex_buffer,
|
||||||
|
&vertex_buffer_offset);
|
||||||
|
|
||||||
|
// Bind the indices.
|
||||||
|
batch_has_index_buffer_ = batch.indices != nullptr;
|
||||||
|
if (batch_has_index_buffer_) {
|
||||||
|
size_t index_buffer_size = sizeof(uint16_t) * batch.index_count;
|
||||||
|
VkBuffer index_buffer;
|
||||||
|
VkDeviceSize index_buffer_offset;
|
||||||
|
void* index_buffer_mapping = vertex_buffer_pool_->Request(
|
||||||
|
submission_current, index_buffer_size, sizeof(uint16_t), index_buffer,
|
||||||
|
index_buffer_offset);
|
||||||
|
if (!index_buffer_mapping) {
|
||||||
|
XELOGE("Failed to get a buffer for {} indices in the immediate drawer",
|
||||||
|
batch.index_count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::memcpy(index_buffer_mapping, batch.indices, index_buffer_size);
|
||||||
|
dfn.vkCmdBindIndexBuffer(current_command_buffer_, index_buffer,
|
||||||
|
index_buffer_offset, VK_INDEX_TYPE_UINT16);
|
||||||
|
}
|
||||||
|
|
||||||
|
batch_open_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanImmediateDrawer::Draw(const ImmediateDraw& draw) {
|
||||||
|
if (!batch_open_) {
|
||||||
|
// No surface, or failed to create the pipelines, or could be an error while
|
||||||
|
// obtaining the vertex and index buffers.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VulkanProvider::DeviceFunctions& dfn =
|
||||||
|
context_.GetVulkanProvider().dfn();
|
||||||
|
|
||||||
|
// Bind the pipeline for the current primitive count.
|
||||||
|
VkPipeline pipeline;
|
||||||
|
switch (draw.primitive_type) {
|
||||||
|
case ImmediatePrimitiveType::kLines:
|
||||||
|
pipeline = pipeline_line_;
|
||||||
|
break;
|
||||||
|
case ImmediatePrimitiveType::kTriangles:
|
||||||
|
pipeline = pipeline_triangle_;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert_unhandled_case(draw.primitive_type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (current_pipeline_ != pipeline) {
|
||||||
|
current_pipeline_ = pipeline;
|
||||||
|
dfn.vkCmdBindPipeline(current_command_buffer_,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the scissor rectangle if enabled.
|
||||||
|
VkRect2D scissor;
|
||||||
|
if (draw.scissor) {
|
||||||
|
scissor.offset.x = draw.scissor_rect[0];
|
||||||
|
scissor.offset.y = current_render_target_extent_.height -
|
||||||
|
(draw.scissor_rect[1] + draw.scissor_rect[3]);
|
||||||
|
scissor.extent.width = draw.scissor_rect[2];
|
||||||
|
scissor.extent.height = draw.scissor_rect[3];
|
||||||
|
} else {
|
||||||
|
scissor.offset.x = 0;
|
||||||
|
scissor.offset.y = 0;
|
||||||
|
scissor.extent = current_render_target_extent_;
|
||||||
|
}
|
||||||
|
dfn.vkCmdSetScissor(current_command_buffer_, 0, 1, &scissor);
|
||||||
|
|
||||||
|
// Draw.
|
||||||
|
if (batch_has_index_buffer_) {
|
||||||
|
dfn.vkCmdDrawIndexed(current_command_buffer_, draw.count, 1,
|
||||||
|
draw.index_offset, draw.base_vertex, 0);
|
||||||
|
} else {
|
||||||
|
dfn.vkCmdDraw(current_command_buffer_, draw.count, 1, draw.base_vertex, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanImmediateDrawer::EndDrawBatch() { batch_open_ = false; }
|
||||||
|
|
||||||
|
void VulkanImmediateDrawer::End() {
|
||||||
|
assert_false(batch_open_);
|
||||||
|
if (current_command_buffer_ == VK_NULL_HANDLE) {
|
||||||
|
// Didn't draw anything because the of some issue or surface not being
|
||||||
|
// available.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vertex_buffer_pool_->FlushWrites();
|
||||||
|
current_command_buffer_ = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VulkanImmediateDrawer::EnsurePipelinesCreated() {
|
||||||
|
VkFormat swap_surface_format = context_.swap_surface_format().format;
|
||||||
|
if (swap_surface_format == pipeline_framebuffer_format_) {
|
||||||
|
// Either created, or failed to create once (don't try to create every
|
||||||
|
// frame).
|
||||||
|
return pipeline_triangle_ != VK_NULL_HANDLE &&
|
||||||
|
pipeline_line_ != VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
VkRenderPass swap_render_pass = context_.swap_render_pass();
|
||||||
|
if (swap_surface_format == VK_FORMAT_UNDEFINED ||
|
||||||
|
swap_render_pass == VK_NULL_HANDLE) {
|
||||||
|
// Not ready yet.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VulkanProvider& provider = context_.GetVulkanProvider();
|
||||||
|
const VulkanProvider::DeviceFunctions& dfn = provider.dfn();
|
||||||
|
VkDevice device = provider.device();
|
||||||
|
|
||||||
|
// Safe to destroy the pipelines now - if the render pass was recreated,
|
||||||
|
// completion of its usage has already been awaited.
|
||||||
|
util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_line_);
|
||||||
|
util::DestroyAndNullHandle(dfn.vkDestroyPipeline, device, pipeline_triangle_);
|
||||||
|
// If creation fails now, don't try to create every frame.
|
||||||
|
pipeline_framebuffer_format_ = swap_surface_format;
|
||||||
|
|
||||||
|
// Triangle pipeline.
|
||||||
|
|
||||||
|
VkPipelineShaderStageCreateInfo stages[2] = {};
|
||||||
|
stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
|
stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
stages[0].module = util::CreateShaderModule(provider, immediate_vert,
|
||||||
|
sizeof(immediate_vert));
|
||||||
|
if (stages[0].module == VK_NULL_HANDLE) {
|
||||||
|
XELOGE("Failed to create the immediate drawer Vulkan vertex shader module");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
stages[0].pName = "main";
|
||||||
|
stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
|
stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
stages[1].module = util::CreateShaderModule(provider, immediate_frag,
|
||||||
|
sizeof(immediate_frag));
|
||||||
|
if (stages[1].module == VK_NULL_HANDLE) {
|
||||||
|
XELOGE(
|
||||||
|
"Failed to create the immediate drawer Vulkan fragment shader module");
|
||||||
|
dfn.vkDestroyShaderModule(device, stages[0].module, nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
stages[1].pName = "main";
|
||||||
|
|
||||||
|
VkVertexInputBindingDescription vertex_input_binding;
|
||||||
|
vertex_input_binding.binding = 0;
|
||||||
|
vertex_input_binding.stride = sizeof(ImmediateVertex);
|
||||||
|
vertex_input_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||||||
|
VkVertexInputAttributeDescription vertex_input_attributes[3];
|
||||||
|
vertex_input_attributes[0].location = 0;
|
||||||
|
vertex_input_attributes[0].binding = 0;
|
||||||
|
vertex_input_attributes[0].format = VK_FORMAT_R32G32_SFLOAT;
|
||||||
|
vertex_input_attributes[0].offset = offsetof(ImmediateVertex, x);
|
||||||
|
vertex_input_attributes[1].location = 1;
|
||||||
|
vertex_input_attributes[1].binding = 0;
|
||||||
|
vertex_input_attributes[1].format = VK_FORMAT_R32G32_SFLOAT;
|
||||||
|
vertex_input_attributes[1].offset = offsetof(ImmediateVertex, u);
|
||||||
|
vertex_input_attributes[2].location = 2;
|
||||||
|
vertex_input_attributes[2].binding = 0;
|
||||||
|
vertex_input_attributes[2].format = VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
vertex_input_attributes[2].offset = offsetof(ImmediateVertex, color);
|
||||||
|
VkPipelineVertexInputStateCreateInfo vertex_input_state;
|
||||||
|
vertex_input_state.sType =
|
||||||
|
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
vertex_input_state.pNext = nullptr;
|
||||||
|
vertex_input_state.flags = 0;
|
||||||
|
vertex_input_state.vertexBindingDescriptionCount = 1;
|
||||||
|
vertex_input_state.pVertexBindingDescriptions = &vertex_input_binding;
|
||||||
|
vertex_input_state.vertexAttributeDescriptionCount =
|
||||||
|
uint32_t(xe::countof(vertex_input_attributes));
|
||||||
|
vertex_input_state.pVertexAttributeDescriptions = vertex_input_attributes;
|
||||||
|
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo input_assembly_state;
|
||||||
|
input_assembly_state.sType =
|
||||||
|
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||||
|
input_assembly_state.pNext = nullptr;
|
||||||
|
input_assembly_state.flags = 0;
|
||||||
|
input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
input_assembly_state.primitiveRestartEnable = VK_FALSE;
|
||||||
|
|
||||||
|
VkPipelineViewportStateCreateInfo viewport_state;
|
||||||
|
viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||||
|
viewport_state.pNext = nullptr;
|
||||||
|
viewport_state.flags = 0;
|
||||||
|
viewport_state.viewportCount = 1;
|
||||||
|
viewport_state.pViewports = nullptr;
|
||||||
|
viewport_state.scissorCount = 1;
|
||||||
|
viewport_state.pScissors = nullptr;
|
||||||
|
|
||||||
|
VkPipelineRasterizationStateCreateInfo rasterization_state = {};
|
||||||
|
rasterization_state.sType =
|
||||||
|
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||||
|
rasterization_state.polygonMode = VK_POLYGON_MODE_FILL;
|
||||||
|
rasterization_state.cullMode = VK_CULL_MODE_NONE;
|
||||||
|
rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||||
|
rasterization_state.lineWidth = 1.0f;
|
||||||
|
|
||||||
|
VkPipelineMultisampleStateCreateInfo multisample_state = {};
|
||||||
|
multisample_state.sType =
|
||||||
|
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||||
|
multisample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
|
||||||
|
VkPipelineColorBlendAttachmentState color_blend_attachment_state;
|
||||||
|
color_blend_attachment_state.blendEnable = VK_TRUE;
|
||||||
|
color_blend_attachment_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||||
|
color_blend_attachment_state.dstColorBlendFactor =
|
||||||
|
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||||
|
color_blend_attachment_state.colorBlendOp = VK_BLEND_OP_ADD;
|
||||||
|
// Don't change alpha (always 1).
|
||||||
|
color_blend_attachment_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||||
|
color_blend_attachment_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||||
|
color_blend_attachment_state.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||||
|
color_blend_attachment_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
|
||||||
|
VK_COLOR_COMPONENT_G_BIT |
|
||||||
|
VK_COLOR_COMPONENT_B_BIT;
|
||||||
|
VkPipelineColorBlendStateCreateInfo color_blend_state;
|
||||||
|
color_blend_state.sType =
|
||||||
|
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||||
|
color_blend_state.pNext = nullptr;
|
||||||
|
color_blend_state.flags = 0;
|
||||||
|
color_blend_state.logicOpEnable = VK_FALSE;
|
||||||
|
color_blend_state.logicOp = VK_LOGIC_OP_NO_OP;
|
||||||
|
color_blend_state.attachmentCount = 1;
|
||||||
|
color_blend_state.pAttachments = &color_blend_attachment_state;
|
||||||
|
color_blend_state.blendConstants[0] = 1.0f;
|
||||||
|
color_blend_state.blendConstants[1] = 1.0f;
|
||||||
|
color_blend_state.blendConstants[2] = 1.0f;
|
||||||
|
color_blend_state.blendConstants[3] = 1.0f;
|
||||||
|
|
||||||
|
static const VkDynamicState dynamic_states[] = {
|
||||||
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
|
VK_DYNAMIC_STATE_SCISSOR,
|
||||||
|
};
|
||||||
|
VkPipelineDynamicStateCreateInfo dynamic_state;
|
||||||
|
dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||||
|
dynamic_state.pNext = nullptr;
|
||||||
|
dynamic_state.flags = 0;
|
||||||
|
dynamic_state.dynamicStateCount = uint32_t(xe::countof(dynamic_states));
|
||||||
|
dynamic_state.pDynamicStates = dynamic_states;
|
||||||
|
|
||||||
|
VkGraphicsPipelineCreateInfo pipeline_create_info;
|
||||||
|
pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
|
||||||
|
pipeline_create_info.pNext = nullptr;
|
||||||
|
pipeline_create_info.flags = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT;
|
||||||
|
pipeline_create_info.stageCount = uint32_t(xe::countof(stages));
|
||||||
|
pipeline_create_info.pStages = stages;
|
||||||
|
pipeline_create_info.pVertexInputState = &vertex_input_state;
|
||||||
|
pipeline_create_info.pInputAssemblyState = &input_assembly_state;
|
||||||
|
pipeline_create_info.pTessellationState = nullptr;
|
||||||
|
pipeline_create_info.pViewportState = &viewport_state;
|
||||||
|
pipeline_create_info.pRasterizationState = &rasterization_state;
|
||||||
|
pipeline_create_info.pMultisampleState = &multisample_state;
|
||||||
|
pipeline_create_info.pDepthStencilState = nullptr;
|
||||||
|
pipeline_create_info.pColorBlendState = &color_blend_state;
|
||||||
|
pipeline_create_info.pDynamicState = &dynamic_state;
|
||||||
|
pipeline_create_info.layout = pipeline_layout_;
|
||||||
|
pipeline_create_info.renderPass = swap_render_pass;
|
||||||
|
pipeline_create_info.subpass = 0;
|
||||||
|
pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
|
||||||
|
pipeline_create_info.basePipelineIndex = -1;
|
||||||
|
if (dfn.vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1,
|
||||||
|
&pipeline_create_info, nullptr,
|
||||||
|
&pipeline_triangle_) != VK_SUCCESS) {
|
||||||
|
XELOGE(
|
||||||
|
"Failed to create the immediate drawer triangle list Vulkan pipeline");
|
||||||
|
dfn.vkDestroyShaderModule(device, stages[1].module, nullptr);
|
||||||
|
dfn.vkDestroyShaderModule(device, stages[0].module, nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Line pipeline.
|
||||||
|
|
||||||
|
input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
|
||||||
|
pipeline_create_info.flags =
|
||||||
|
(pipeline_create_info.flags & ~VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT) |
|
||||||
|
VK_PIPELINE_CREATE_DERIVATIVE_BIT;
|
||||||
|
pipeline_create_info.basePipelineHandle = pipeline_triangle_;
|
||||||
|
VkResult pipeline_line_create_result = dfn.vkCreateGraphicsPipelines(
|
||||||
|
device, VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr,
|
||||||
|
&pipeline_line_);
|
||||||
|
dfn.vkDestroyShaderModule(device, stages[1].module, nullptr);
|
||||||
|
dfn.vkDestroyShaderModule(device, stages[0].module, nullptr);
|
||||||
|
if (pipeline_line_create_result != VK_SUCCESS) {
|
||||||
|
XELOGE("Failed to create the immediate drawer line list Vulkan pipeline");
|
||||||
|
dfn.vkDestroyPipeline(device, pipeline_triangle_, nullptr);
|
||||||
|
pipeline_triangle_ = VK_NULL_HANDLE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace vulkan
|
} // namespace vulkan
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|
|
@ -10,7 +10,10 @@
|
||||||
#ifndef XENIA_UI_VULKAN_VULKAN_IMMEDIATE_DRAWER_H_
|
#ifndef XENIA_UI_VULKAN_VULKAN_IMMEDIATE_DRAWER_H_
|
||||||
#define XENIA_UI_VULKAN_VULKAN_IMMEDIATE_DRAWER_H_
|
#define XENIA_UI_VULKAN_VULKAN_IMMEDIATE_DRAWER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "xenia/ui/immediate_drawer.h"
|
#include "xenia/ui/immediate_drawer.h"
|
||||||
|
#include "xenia/ui/vulkan/vulkan_upload_buffer_pool.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
@ -21,6 +24,10 @@ class VulkanContext;
|
||||||
class VulkanImmediateDrawer : public ImmediateDrawer {
|
class VulkanImmediateDrawer : public ImmediateDrawer {
|
||||||
public:
|
public:
|
||||||
VulkanImmediateDrawer(VulkanContext& graphics_context);
|
VulkanImmediateDrawer(VulkanContext& graphics_context);
|
||||||
|
~VulkanImmediateDrawer() override;
|
||||||
|
|
||||||
|
bool Initialize();
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
std::unique_ptr<ImmediateTexture> CreateTexture(uint32_t width,
|
std::unique_ptr<ImmediateTexture> CreateTexture(uint32_t width,
|
||||||
uint32_t height,
|
uint32_t height,
|
||||||
|
@ -36,7 +43,29 @@ class VulkanImmediateDrawer : public ImmediateDrawer {
|
||||||
void End() override;
|
void End() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct PushConstants {
|
||||||
|
struct Vertex {
|
||||||
|
float viewport_size_inv[2];
|
||||||
|
} vertex;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool EnsurePipelinesCreated();
|
||||||
|
|
||||||
VulkanContext& context_;
|
VulkanContext& context_;
|
||||||
|
|
||||||
|
VkPipelineLayout pipeline_layout_ = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
std::unique_ptr<VulkanUploadBufferPool> vertex_buffer_pool_;
|
||||||
|
|
||||||
|
VkFormat pipeline_framebuffer_format_ = VK_FORMAT_UNDEFINED;
|
||||||
|
VkPipeline pipeline_triangle_ = VK_NULL_HANDLE;
|
||||||
|
VkPipeline pipeline_line_ = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
VkCommandBuffer current_command_buffer_ = VK_NULL_HANDLE;
|
||||||
|
VkExtent2D current_render_target_extent_;
|
||||||
|
VkPipeline current_pipeline_;
|
||||||
|
bool batch_open_ = false;
|
||||||
|
bool batch_has_index_buffer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace vulkan
|
} // namespace vulkan
|
||||||
|
|
|
@ -131,12 +131,16 @@ bool VulkanProvider::Initialize() {
|
||||||
const uint32_t api_version_target = VK_MAKE_VERSION(1, 2, 148);
|
const uint32_t api_version_target = VK_MAKE_VERSION(1, 2, 148);
|
||||||
static_assert(VK_HEADER_VERSION_COMPLETE >= api_version_target,
|
static_assert(VK_HEADER_VERSION_COMPLETE >= api_version_target,
|
||||||
"Vulkan header files must be up to date");
|
"Vulkan header files must be up to date");
|
||||||
|
uint32_t instance_api_version;
|
||||||
if (!lfn_.v_1_1.vkEnumerateInstanceVersion ||
|
if (!lfn_.v_1_1.vkEnumerateInstanceVersion ||
|
||||||
lfn_.v_1_1.vkEnumerateInstanceVersion(&api_version_) != VK_SUCCESS) {
|
lfn_.v_1_1.vkEnumerateInstanceVersion(&instance_api_version) !=
|
||||||
api_version_ = VK_API_VERSION_1_0;
|
VK_SUCCESS) {
|
||||||
|
instance_api_version = VK_API_VERSION_1_0;
|
||||||
}
|
}
|
||||||
XELOGVK("Vulkan instance version {}.{}.{}", VK_VERSION_MAJOR(api_version_),
|
XELOGVK("Vulkan instance version {}.{}.{}",
|
||||||
VK_VERSION_MINOR(api_version_), VK_VERSION_PATCH(api_version_));
|
VK_VERSION_MAJOR(instance_api_version),
|
||||||
|
VK_VERSION_MINOR(instance_api_version),
|
||||||
|
VK_VERSION_PATCH(instance_api_version));
|
||||||
|
|
||||||
// Create the instance.
|
// Create the instance.
|
||||||
std::vector<const char*> instance_extensions_enabled;
|
std::vector<const char*> instance_extensions_enabled;
|
||||||
|
@ -157,9 +161,9 @@ bool VulkanProvider::Initialize() {
|
||||||
// designed to use"
|
// designed to use"
|
||||||
// "Vulkan 1.0 implementations were required to return
|
// "Vulkan 1.0 implementations were required to return
|
||||||
// VK_ERROR_INCOMPATIBLE_DRIVER if apiVersion was larger than 1.0"
|
// VK_ERROR_INCOMPATIBLE_DRIVER if apiVersion was larger than 1.0"
|
||||||
application_info.apiVersion = api_version_ >= VK_MAKE_VERSION(1, 1, 0)
|
application_info.apiVersion = instance_api_version >= VK_MAKE_VERSION(1, 1, 0)
|
||||||
? api_version_target
|
? api_version_target
|
||||||
: api_version_;
|
: instance_api_version;
|
||||||
VkInstanceCreateInfo instance_create_info;
|
VkInstanceCreateInfo instance_create_info;
|
||||||
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
instance_create_info.pNext = nullptr;
|
instance_create_info.pNext = nullptr;
|
||||||
|
@ -207,6 +211,7 @@ bool VulkanProvider::Initialize() {
|
||||||
XE_VULKAN_LOAD_IFN(vkGetDeviceProcAddr);
|
XE_VULKAN_LOAD_IFN(vkGetDeviceProcAddr);
|
||||||
XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceFeatures);
|
XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceFeatures);
|
||||||
XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceProperties);
|
XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceProperties);
|
||||||
|
XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceMemoryProperties);
|
||||||
XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceQueueFamilyProperties);
|
XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceQueueFamilyProperties);
|
||||||
XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
|
XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
|
||||||
XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceSurfaceFormatsKHR);
|
XE_VULKAN_LOAD_IFN(vkGetPhysicalDeviceSurfaceFormatsKHR);
|
||||||
|
@ -344,6 +349,11 @@ bool VulkanProvider::Initialize() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get device properties, will be needed to check if extensions have been
|
||||||
|
// promoted to core.
|
||||||
|
ifn_.vkGetPhysicalDeviceProperties(physical_device_current,
|
||||||
|
&device_properties_);
|
||||||
|
|
||||||
// Get the extensions, check if swapchain is supported.
|
// Get the extensions, check if swapchain is supported.
|
||||||
device_extension_properties.clear();
|
device_extension_properties.clear();
|
||||||
VkResult device_extensions_enumerate_result;
|
VkResult device_extensions_enumerate_result;
|
||||||
|
@ -373,14 +383,23 @@ bool VulkanProvider::Initialize() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::memset(&device_extensions_, 0, sizeof(device_extensions_));
|
std::memset(&device_extensions_, 0, sizeof(device_extensions_));
|
||||||
|
if (device_properties_.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
|
||||||
|
device_extensions_.khr_dedicated_allocation = true;
|
||||||
|
}
|
||||||
bool device_supports_swapchain = false;
|
bool device_supports_swapchain = false;
|
||||||
for (const VkExtensionProperties& device_extension :
|
for (const VkExtensionProperties& device_extension :
|
||||||
device_extension_properties) {
|
device_extension_properties) {
|
||||||
const char* device_extension_name = device_extension.extensionName;
|
const char* device_extension_name = device_extension.extensionName;
|
||||||
if (!std::strcmp(device_extension_name,
|
if (!device_extensions_.ext_fragment_shader_interlock &&
|
||||||
|
!std::strcmp(device_extension_name,
|
||||||
"VK_EXT_fragment_shader_interlock")) {
|
"VK_EXT_fragment_shader_interlock")) {
|
||||||
device_extensions_.ext_fragment_shader_interlock = true;
|
device_extensions_.ext_fragment_shader_interlock = true;
|
||||||
} else if (!std::strcmp(device_extension_name, "VK_KHR_swapchain")) {
|
} else if (!device_extensions_.khr_dedicated_allocation &&
|
||||||
|
!std::strcmp(device_extension_name,
|
||||||
|
"VK_KHR_dedicated_allocation")) {
|
||||||
|
device_extensions_.khr_dedicated_allocation = true;
|
||||||
|
} else if (!device_supports_swapchain &&
|
||||||
|
!std::strcmp(device_extension_name, "VK_KHR_swapchain")) {
|
||||||
device_supports_swapchain = true;
|
device_supports_swapchain = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,6 +407,32 @@ bool VulkanProvider::Initialize() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the memory types.
|
||||||
|
VkPhysicalDeviceMemoryProperties memory_properties;
|
||||||
|
ifn_.vkGetPhysicalDeviceMemoryProperties(physical_device_current,
|
||||||
|
&memory_properties);
|
||||||
|
memory_types_device_local_ = 0;
|
||||||
|
memory_types_host_visible_ = 0;
|
||||||
|
memory_types_host_coherent_ = 0;
|
||||||
|
for (uint32_t j = 0; j < memory_properties.memoryTypeCount; ++j) {
|
||||||
|
VkMemoryPropertyFlags memory_property_flags =
|
||||||
|
memory_properties.memoryTypes[j].propertyFlags;
|
||||||
|
uint32_t memory_type_bit = uint32_t(1) << j;
|
||||||
|
if (memory_property_flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
|
||||||
|
memory_types_device_local_ |= memory_type_bit;
|
||||||
|
}
|
||||||
|
if (memory_property_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
|
||||||
|
memory_types_host_visible_ |= memory_type_bit;
|
||||||
|
}
|
||||||
|
if (memory_property_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
|
||||||
|
memory_types_host_coherent_ |= memory_type_bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!memory_types_device_local_ && !memory_types_host_visible_) {
|
||||||
|
// Shouldn't happen according to the specification.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
physical_device_ = physical_device_current;
|
physical_device_ = physical_device_current;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -397,7 +442,6 @@ bool VulkanProvider::Initialize() {
|
||||||
"support");
|
"support");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ifn_.vkGetPhysicalDeviceProperties(physical_device_, &device_properties_);
|
|
||||||
XELOGVK(
|
XELOGVK(
|
||||||
"Vulkan device: {} (vendor {:04X}, device {:04X}, driver {:08X}, API "
|
"Vulkan device: {} (vendor {:04X}, device {:04X}, driver {:08X}, API "
|
||||||
"{}.{}.{})",
|
"{}.{}.{})",
|
||||||
|
@ -406,7 +450,12 @@ bool VulkanProvider::Initialize() {
|
||||||
VK_VERSION_MAJOR(device_properties_.apiVersion),
|
VK_VERSION_MAJOR(device_properties_.apiVersion),
|
||||||
VK_VERSION_MINOR(device_properties_.apiVersion),
|
VK_VERSION_MINOR(device_properties_.apiVersion),
|
||||||
VK_VERSION_PATCH(device_properties_.apiVersion));
|
VK_VERSION_PATCH(device_properties_.apiVersion));
|
||||||
// TODO(Triang3l): Report properties, features, extensions.
|
XELOGVK("Vulkan device extensions:");
|
||||||
|
XELOGVK("* VK_EXT_fragment_shader_interlock: {}",
|
||||||
|
device_extensions_.ext_fragment_shader_interlock ? "yes" : "no");
|
||||||
|
XELOGVK("* VK_KHR_dedicated_allocation: {}",
|
||||||
|
device_extensions_.khr_dedicated_allocation ? "yes" : "no");
|
||||||
|
// TODO(Triang3l): Report properties, features.
|
||||||
|
|
||||||
// Create the device.
|
// Create the device.
|
||||||
float queue_priority_high = 1.0f;
|
float queue_priority_high = 1.0f;
|
||||||
|
@ -433,6 +482,11 @@ bool VulkanProvider::Initialize() {
|
||||||
if (device_extensions_.ext_fragment_shader_interlock) {
|
if (device_extensions_.ext_fragment_shader_interlock) {
|
||||||
device_extensions_enabled.push_back("VK_EXT_fragment_shader_interlock");
|
device_extensions_enabled.push_back("VK_EXT_fragment_shader_interlock");
|
||||||
}
|
}
|
||||||
|
if (device_properties_.apiVersion < VK_MAKE_VERSION(1, 1, 0)) {
|
||||||
|
if (device_extensions_.khr_dedicated_allocation) {
|
||||||
|
device_extensions_enabled.push_back("VK_KHR_dedicated_allocation");
|
||||||
|
}
|
||||||
|
}
|
||||||
VkDeviceCreateInfo device_create_info;
|
VkDeviceCreateInfo device_create_info;
|
||||||
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
device_create_info.pNext = nullptr;
|
device_create_info.pNext = nullptr;
|
||||||
|
@ -462,26 +516,48 @@ bool VulkanProvider::Initialize() {
|
||||||
nullptr;
|
nullptr;
|
||||||
XE_VULKAN_LOAD_DFN(vkAcquireNextImageKHR);
|
XE_VULKAN_LOAD_DFN(vkAcquireNextImageKHR);
|
||||||
XE_VULKAN_LOAD_DFN(vkAllocateCommandBuffers);
|
XE_VULKAN_LOAD_DFN(vkAllocateCommandBuffers);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkAllocateMemory);
|
||||||
XE_VULKAN_LOAD_DFN(vkBeginCommandBuffer);
|
XE_VULKAN_LOAD_DFN(vkBeginCommandBuffer);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkBindBufferMemory);
|
||||||
XE_VULKAN_LOAD_DFN(vkCmdBeginRenderPass);
|
XE_VULKAN_LOAD_DFN(vkCmdBeginRenderPass);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkCmdBindIndexBuffer);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkCmdBindPipeline);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkCmdBindVertexBuffers);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkCmdDraw);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkCmdDrawIndexed);
|
||||||
XE_VULKAN_LOAD_DFN(vkCmdEndRenderPass);
|
XE_VULKAN_LOAD_DFN(vkCmdEndRenderPass);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkCmdPushConstants);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkCmdSetScissor);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkCmdSetViewport);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkCreateBuffer);
|
||||||
XE_VULKAN_LOAD_DFN(vkCreateCommandPool);
|
XE_VULKAN_LOAD_DFN(vkCreateCommandPool);
|
||||||
XE_VULKAN_LOAD_DFN(vkCreateFence);
|
XE_VULKAN_LOAD_DFN(vkCreateFence);
|
||||||
XE_VULKAN_LOAD_DFN(vkCreateFramebuffer);
|
XE_VULKAN_LOAD_DFN(vkCreateFramebuffer);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkCreateGraphicsPipelines);
|
||||||
XE_VULKAN_LOAD_DFN(vkCreateImageView);
|
XE_VULKAN_LOAD_DFN(vkCreateImageView);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkCreatePipelineLayout);
|
||||||
XE_VULKAN_LOAD_DFN(vkCreateRenderPass);
|
XE_VULKAN_LOAD_DFN(vkCreateRenderPass);
|
||||||
XE_VULKAN_LOAD_DFN(vkCreateSemaphore);
|
XE_VULKAN_LOAD_DFN(vkCreateSemaphore);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkCreateShaderModule);
|
||||||
XE_VULKAN_LOAD_DFN(vkCreateSwapchainKHR);
|
XE_VULKAN_LOAD_DFN(vkCreateSwapchainKHR);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkDestroyBuffer);
|
||||||
XE_VULKAN_LOAD_DFN(vkDestroyCommandPool);
|
XE_VULKAN_LOAD_DFN(vkDestroyCommandPool);
|
||||||
XE_VULKAN_LOAD_DFN(vkDestroyFence);
|
XE_VULKAN_LOAD_DFN(vkDestroyFence);
|
||||||
XE_VULKAN_LOAD_DFN(vkDestroyFramebuffer);
|
XE_VULKAN_LOAD_DFN(vkDestroyFramebuffer);
|
||||||
XE_VULKAN_LOAD_DFN(vkDestroyImageView);
|
XE_VULKAN_LOAD_DFN(vkDestroyImageView);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkDestroyPipeline);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkDestroyPipelineLayout);
|
||||||
XE_VULKAN_LOAD_DFN(vkDestroyRenderPass);
|
XE_VULKAN_LOAD_DFN(vkDestroyRenderPass);
|
||||||
XE_VULKAN_LOAD_DFN(vkDestroySemaphore);
|
XE_VULKAN_LOAD_DFN(vkDestroySemaphore);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkDestroyShaderModule);
|
||||||
XE_VULKAN_LOAD_DFN(vkDestroySwapchainKHR);
|
XE_VULKAN_LOAD_DFN(vkDestroySwapchainKHR);
|
||||||
XE_VULKAN_LOAD_DFN(vkEndCommandBuffer);
|
XE_VULKAN_LOAD_DFN(vkEndCommandBuffer);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkFlushMappedMemoryRanges);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkFreeMemory);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkGetBufferMemoryRequirements);
|
||||||
XE_VULKAN_LOAD_DFN(vkGetDeviceQueue);
|
XE_VULKAN_LOAD_DFN(vkGetDeviceQueue);
|
||||||
XE_VULKAN_LOAD_DFN(vkGetSwapchainImagesKHR);
|
XE_VULKAN_LOAD_DFN(vkGetSwapchainImagesKHR);
|
||||||
|
XE_VULKAN_LOAD_DFN(vkMapMemory);
|
||||||
XE_VULKAN_LOAD_DFN(vkResetCommandPool);
|
XE_VULKAN_LOAD_DFN(vkResetCommandPool);
|
||||||
XE_VULKAN_LOAD_DFN(vkResetFences);
|
XE_VULKAN_LOAD_DFN(vkResetFences);
|
||||||
XE_VULKAN_LOAD_DFN(vkQueuePresentKHR);
|
XE_VULKAN_LOAD_DFN(vkQueuePresentKHR);
|
||||||
|
|
|
@ -59,8 +59,6 @@ class VulkanProvider : public GraphicsProvider {
|
||||||
};
|
};
|
||||||
const LibraryFunctions& lfn() const { return lfn_; }
|
const LibraryFunctions& lfn() const { return lfn_; }
|
||||||
|
|
||||||
uint32_t api_version() const { return api_version_; }
|
|
||||||
|
|
||||||
VkInstance instance() const { return instance_; }
|
VkInstance instance() const { return instance_; }
|
||||||
struct InstanceFunctions {
|
struct InstanceFunctions {
|
||||||
PFN_vkCreateDevice vkCreateDevice;
|
PFN_vkCreateDevice vkCreateDevice;
|
||||||
|
@ -71,6 +69,7 @@ class VulkanProvider : public GraphicsProvider {
|
||||||
PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
|
PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
|
||||||
PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
|
PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
|
||||||
PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures;
|
PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures;
|
||||||
|
PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
|
||||||
PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
|
PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
|
||||||
PFN_vkGetPhysicalDeviceQueueFamilyProperties
|
PFN_vkGetPhysicalDeviceQueueFamilyProperties
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties;
|
vkGetPhysicalDeviceQueueFamilyProperties;
|
||||||
|
@ -99,10 +98,21 @@ class VulkanProvider : public GraphicsProvider {
|
||||||
}
|
}
|
||||||
struct DeviceExtensions {
|
struct DeviceExtensions {
|
||||||
bool ext_fragment_shader_interlock;
|
bool ext_fragment_shader_interlock;
|
||||||
|
// Core since 1.1.0.
|
||||||
|
bool khr_dedicated_allocation;
|
||||||
};
|
};
|
||||||
const DeviceExtensions& device_extensions() const {
|
const DeviceExtensions& device_extensions() const {
|
||||||
return device_extensions_;
|
return device_extensions_;
|
||||||
}
|
}
|
||||||
|
uint32_t memory_types_device_local() const {
|
||||||
|
return memory_types_device_local_;
|
||||||
|
}
|
||||||
|
uint32_t memory_types_host_visible() const {
|
||||||
|
return memory_types_host_visible_;
|
||||||
|
}
|
||||||
|
uint32_t memory_types_host_coherent() const {
|
||||||
|
return memory_types_host_coherent_;
|
||||||
|
}
|
||||||
// FIXME(Triang3l): Allow a separate queue for present - see
|
// FIXME(Triang3l): Allow a separate queue for present - see
|
||||||
// vulkan_provider.cc for details.
|
// vulkan_provider.cc for details.
|
||||||
uint32_t queue_family_graphics_compute() const {
|
uint32_t queue_family_graphics_compute() const {
|
||||||
|
@ -113,26 +123,48 @@ class VulkanProvider : public GraphicsProvider {
|
||||||
struct DeviceFunctions {
|
struct DeviceFunctions {
|
||||||
PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
|
PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
|
||||||
PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers;
|
PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers;
|
||||||
|
PFN_vkAllocateMemory vkAllocateMemory;
|
||||||
PFN_vkBeginCommandBuffer vkBeginCommandBuffer;
|
PFN_vkBeginCommandBuffer vkBeginCommandBuffer;
|
||||||
|
PFN_vkBindBufferMemory vkBindBufferMemory;
|
||||||
PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass;
|
PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass;
|
||||||
|
PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer;
|
||||||
|
PFN_vkCmdBindPipeline vkCmdBindPipeline;
|
||||||
|
PFN_vkCmdBindVertexBuffers vkCmdBindVertexBuffers;
|
||||||
|
PFN_vkCmdDraw vkCmdDraw;
|
||||||
|
PFN_vkCmdDrawIndexed vkCmdDrawIndexed;
|
||||||
PFN_vkCmdEndRenderPass vkCmdEndRenderPass;
|
PFN_vkCmdEndRenderPass vkCmdEndRenderPass;
|
||||||
|
PFN_vkCmdPushConstants vkCmdPushConstants;
|
||||||
|
PFN_vkCmdSetScissor vkCmdSetScissor;
|
||||||
|
PFN_vkCmdSetViewport vkCmdSetViewport;
|
||||||
|
PFN_vkCreateBuffer vkCreateBuffer;
|
||||||
PFN_vkCreateCommandPool vkCreateCommandPool;
|
PFN_vkCreateCommandPool vkCreateCommandPool;
|
||||||
PFN_vkCreateFence vkCreateFence;
|
PFN_vkCreateFence vkCreateFence;
|
||||||
PFN_vkCreateFramebuffer vkCreateFramebuffer;
|
PFN_vkCreateFramebuffer vkCreateFramebuffer;
|
||||||
|
PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines;
|
||||||
PFN_vkCreateImageView vkCreateImageView;
|
PFN_vkCreateImageView vkCreateImageView;
|
||||||
|
PFN_vkCreatePipelineLayout vkCreatePipelineLayout;
|
||||||
PFN_vkCreateRenderPass vkCreateRenderPass;
|
PFN_vkCreateRenderPass vkCreateRenderPass;
|
||||||
PFN_vkCreateSemaphore vkCreateSemaphore;
|
PFN_vkCreateSemaphore vkCreateSemaphore;
|
||||||
|
PFN_vkCreateShaderModule vkCreateShaderModule;
|
||||||
PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR;
|
PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR;
|
||||||
|
PFN_vkDestroyBuffer vkDestroyBuffer;
|
||||||
PFN_vkDestroyCommandPool vkDestroyCommandPool;
|
PFN_vkDestroyCommandPool vkDestroyCommandPool;
|
||||||
PFN_vkDestroyFence vkDestroyFence;
|
PFN_vkDestroyFence vkDestroyFence;
|
||||||
PFN_vkDestroyFramebuffer vkDestroyFramebuffer;
|
PFN_vkDestroyFramebuffer vkDestroyFramebuffer;
|
||||||
PFN_vkDestroyImageView vkDestroyImageView;
|
PFN_vkDestroyImageView vkDestroyImageView;
|
||||||
|
PFN_vkDestroyPipeline vkDestroyPipeline;
|
||||||
|
PFN_vkDestroyPipelineLayout vkDestroyPipelineLayout;
|
||||||
PFN_vkDestroyRenderPass vkDestroyRenderPass;
|
PFN_vkDestroyRenderPass vkDestroyRenderPass;
|
||||||
PFN_vkDestroySemaphore vkDestroySemaphore;
|
PFN_vkDestroySemaphore vkDestroySemaphore;
|
||||||
|
PFN_vkDestroyShaderModule vkDestroyShaderModule;
|
||||||
PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
|
PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
|
||||||
PFN_vkEndCommandBuffer vkEndCommandBuffer;
|
PFN_vkEndCommandBuffer vkEndCommandBuffer;
|
||||||
|
PFN_vkFlushMappedMemoryRanges vkFlushMappedMemoryRanges;
|
||||||
|
PFN_vkFreeMemory vkFreeMemory;
|
||||||
|
PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
|
||||||
PFN_vkGetDeviceQueue vkGetDeviceQueue;
|
PFN_vkGetDeviceQueue vkGetDeviceQueue;
|
||||||
PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
|
PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
|
||||||
|
PFN_vkMapMemory vkMapMemory;
|
||||||
PFN_vkResetCommandPool vkResetCommandPool;
|
PFN_vkResetCommandPool vkResetCommandPool;
|
||||||
PFN_vkResetFences vkResetFences;
|
PFN_vkResetFences vkResetFences;
|
||||||
PFN_vkQueuePresentKHR vkQueuePresentKHR;
|
PFN_vkQueuePresentKHR vkQueuePresentKHR;
|
||||||
|
@ -158,8 +190,6 @@ class VulkanProvider : public GraphicsProvider {
|
||||||
|
|
||||||
LibraryFunctions lfn_ = {};
|
LibraryFunctions lfn_ = {};
|
||||||
|
|
||||||
uint32_t api_version_ = VK_API_VERSION_1_0;
|
|
||||||
|
|
||||||
VkInstance instance_ = VK_NULL_HANDLE;
|
VkInstance instance_ = VK_NULL_HANDLE;
|
||||||
InstanceFunctions ifn_ = {};
|
InstanceFunctions ifn_ = {};
|
||||||
|
|
||||||
|
@ -167,6 +197,9 @@ class VulkanProvider : public GraphicsProvider {
|
||||||
VkPhysicalDeviceProperties device_properties_;
|
VkPhysicalDeviceProperties device_properties_;
|
||||||
VkPhysicalDeviceFeatures device_features_;
|
VkPhysicalDeviceFeatures device_features_;
|
||||||
DeviceExtensions device_extensions_;
|
DeviceExtensions device_extensions_;
|
||||||
|
uint32_t memory_types_device_local_;
|
||||||
|
uint32_t memory_types_host_visible_;
|
||||||
|
uint32_t memory_types_host_coherent_;
|
||||||
uint32_t queue_family_graphics_compute_;
|
uint32_t queue_family_graphics_compute_;
|
||||||
|
|
||||||
VkDevice device_ = VK_NULL_HANDLE;
|
VkDevice device_ = VK_NULL_HANDLE;
|
||||||
|
|
|
@ -0,0 +1,227 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xenia/ui/vulkan/vulkan_upload_buffer_pool.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "xenia/base/logging.h"
|
||||||
|
#include "xenia/base/math.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace ui {
|
||||||
|
namespace vulkan {
|
||||||
|
|
||||||
|
VulkanUploadBufferPool::VulkanUploadBufferPool(const VulkanProvider& provider,
|
||||||
|
VkBufferUsageFlags usage,
|
||||||
|
size_t page_size)
|
||||||
|
: GraphicsUploadBufferPool(page_size), provider_(provider), usage_(usage) {
|
||||||
|
VkDeviceSize non_coherent_atom_size =
|
||||||
|
provider_.device_properties().limits.nonCoherentAtomSize;
|
||||||
|
// Memory mappings are always aligned to nonCoherentAtomSize, so for
|
||||||
|
// simplicity, round the page size to it now. On some Android implementations,
|
||||||
|
// nonCoherentAtomSize is 0, not 1.
|
||||||
|
if (non_coherent_atom_size > 1) {
|
||||||
|
page_size_ = xe::round_up(page_size_, non_coherent_atom_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* VulkanUploadBufferPool::Request(uint64_t submission_index, size_t size,
|
||||||
|
size_t alignment, VkBuffer& buffer_out,
|
||||||
|
VkDeviceSize& offset_out) {
|
||||||
|
size_t offset;
|
||||||
|
const VulkanPage* page =
|
||||||
|
static_cast<const VulkanPage*>(GraphicsUploadBufferPool::Request(
|
||||||
|
submission_index, size, alignment, offset));
|
||||||
|
if (!page) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
buffer_out = page->buffer_;
|
||||||
|
offset_out = VkDeviceSize(offset);
|
||||||
|
return reinterpret_cast<uint8_t*>(page->mapping_) + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* VulkanUploadBufferPool::RequestPartial(uint64_t submission_index,
|
||||||
|
size_t size, size_t alignment,
|
||||||
|
VkBuffer& buffer_out,
|
||||||
|
VkDeviceSize& offset_out,
|
||||||
|
VkDeviceSize& size_out) {
|
||||||
|
size_t offset, size_obtained;
|
||||||
|
const VulkanPage* page =
|
||||||
|
static_cast<const VulkanPage*>(GraphicsUploadBufferPool::RequestPartial(
|
||||||
|
submission_index, size, alignment, offset, size_obtained));
|
||||||
|
if (!page) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
buffer_out = page->buffer_;
|
||||||
|
offset_out = VkDeviceSize(offset);
|
||||||
|
size_out = VkDeviceSize(size_obtained);
|
||||||
|
return reinterpret_cast<uint8_t*>(page->mapping_) + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsUploadBufferPool::Page*
|
||||||
|
VulkanUploadBufferPool::CreatePageImplementation() {
|
||||||
|
if (memory_type_ == kMemoryTypeUnavailable) {
|
||||||
|
// Don't try to create everything again and again if totally broken.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VulkanProvider::DeviceFunctions& dfn = provider_.dfn();
|
||||||
|
VkDevice device = provider_.device();
|
||||||
|
|
||||||
|
// For the first call, the page size is already aligned to nonCoherentAtomSize
|
||||||
|
// for mapping.
|
||||||
|
VkBufferCreateInfo buffer_create_info;
|
||||||
|
buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||||
|
buffer_create_info.pNext = nullptr;
|
||||||
|
buffer_create_info.flags = 0;
|
||||||
|
buffer_create_info.size = VkDeviceSize(page_size_);
|
||||||
|
buffer_create_info.usage = usage_;
|
||||||
|
buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
buffer_create_info.queueFamilyIndexCount = 0;
|
||||||
|
buffer_create_info.pQueueFamilyIndices = nullptr;
|
||||||
|
VkBuffer buffer;
|
||||||
|
if (dfn.vkCreateBuffer(device, &buffer_create_info, nullptr, &buffer) !=
|
||||||
|
VK_SUCCESS) {
|
||||||
|
XELOGE("Failed to create a Vulkan upload buffer with {} bytes", page_size_);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memory_type_ == kMemoryTypeUnknown) {
|
||||||
|
VkMemoryRequirements memory_requirements;
|
||||||
|
dfn.vkGetBufferMemoryRequirements(device, buffer, &memory_requirements);
|
||||||
|
uint32_t memory_types_host_visible = provider_.memory_types_host_visible();
|
||||||
|
if (!xe::bit_scan_forward(
|
||||||
|
memory_requirements.memoryTypeBits & memory_types_host_visible,
|
||||||
|
&memory_type_)) {
|
||||||
|
XELOGE(
|
||||||
|
"No host-visible memory types can store an Vulkan upload buffer with "
|
||||||
|
"{} bytes",
|
||||||
|
page_size_);
|
||||||
|
memory_type_ = kMemoryTypeUnavailable;
|
||||||
|
dfn.vkDestroyBuffer(device, buffer, nullptr);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
allocation_size_ = memory_requirements.size;
|
||||||
|
// On some Android implementations, nonCoherentAtomSize is 0, not 1.
|
||||||
|
VkDeviceSize non_coherent_atom_size =
|
||||||
|
std::max(provider_.device_properties().limits.nonCoherentAtomSize,
|
||||||
|
VkDeviceSize(1));
|
||||||
|
VkDeviceSize allocation_size_aligned =
|
||||||
|
allocation_size_ / non_coherent_atom_size * non_coherent_atom_size;
|
||||||
|
if (allocation_size_aligned > page_size_) {
|
||||||
|
// Try to occupy all the allocation padding. If that's going to require
|
||||||
|
// even more memory for some reason, don't.
|
||||||
|
buffer_create_info.size = allocation_size_aligned;
|
||||||
|
VkBuffer buffer_expanded;
|
||||||
|
if (dfn.vkCreateBuffer(device, &buffer_create_info, nullptr,
|
||||||
|
&buffer_expanded) == VK_SUCCESS) {
|
||||||
|
VkMemoryRequirements memory_requirements_expanded;
|
||||||
|
dfn.vkGetBufferMemoryRequirements(device, buffer_expanded,
|
||||||
|
&memory_requirements_expanded);
|
||||||
|
uint32_t memory_type_expanded;
|
||||||
|
if (memory_requirements_expanded.size <= allocation_size_ &&
|
||||||
|
xe::bit_scan_forward(memory_requirements_expanded.memoryTypeBits &
|
||||||
|
memory_types_host_visible,
|
||||||
|
&memory_type_expanded)) {
|
||||||
|
// page_size_ must be aligned to nonCoherentAtomSize.
|
||||||
|
page_size_ = size_t(allocation_size_aligned);
|
||||||
|
allocation_size_ = memory_requirements_expanded.size;
|
||||||
|
memory_type_ = memory_type_expanded;
|
||||||
|
dfn.vkDestroyBuffer(device, buffer, nullptr);
|
||||||
|
buffer = buffer_expanded;
|
||||||
|
} else {
|
||||||
|
dfn.vkDestroyBuffer(device, buffer_expanded, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkMemoryAllocateInfo memory_allocate_info;
|
||||||
|
memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
|
VkMemoryDedicatedAllocateInfoKHR memory_dedicated_allocate_info;
|
||||||
|
if (provider_.device_extensions().khr_dedicated_allocation) {
|
||||||
|
memory_dedicated_allocate_info.sType =
|
||||||
|
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR;
|
||||||
|
memory_dedicated_allocate_info.pNext = nullptr;
|
||||||
|
memory_dedicated_allocate_info.image = VK_NULL_HANDLE;
|
||||||
|
memory_dedicated_allocate_info.buffer = buffer;
|
||||||
|
memory_allocate_info.pNext = &memory_dedicated_allocate_info;
|
||||||
|
} else {
|
||||||
|
memory_allocate_info.pNext = nullptr;
|
||||||
|
}
|
||||||
|
memory_allocate_info.allocationSize = allocation_size_;
|
||||||
|
memory_allocate_info.memoryTypeIndex = memory_type_;
|
||||||
|
VkDeviceMemory memory;
|
||||||
|
if (dfn.vkAllocateMemory(device, &memory_allocate_info, nullptr, &memory) !=
|
||||||
|
VK_SUCCESS) {
|
||||||
|
XELOGE("Failed to allocate {} bytes of Vulkan upload buffer memory",
|
||||||
|
allocation_size_);
|
||||||
|
dfn.vkDestroyBuffer(device, buffer, nullptr);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dfn.vkBindBufferMemory(device, buffer, memory, 0) != VK_SUCCESS) {
|
||||||
|
XELOGE("Failed to bind memory to a Vulkan upload buffer with {} bytes",
|
||||||
|
page_size_);
|
||||||
|
dfn.vkDestroyBuffer(device, buffer, nullptr);
|
||||||
|
dfn.vkFreeMemory(device, memory, nullptr);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* mapping;
|
||||||
|
// page_size_ is aligned to nonCoherentAtomSize.
|
||||||
|
if (dfn.vkMapMemory(device, memory, 0, page_size_, 0, &mapping) !=
|
||||||
|
VK_SUCCESS) {
|
||||||
|
XELOGE("Failed to map {} bytes of Vulkan upload buffer memory", page_size_);
|
||||||
|
dfn.vkDestroyBuffer(device, buffer, nullptr);
|
||||||
|
dfn.vkFreeMemory(device, memory, nullptr);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new VulkanPage(provider_, buffer, memory, mapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanUploadBufferPool::FlushPageWrites(Page* page, size_t offset,
|
||||||
|
size_t size) {
|
||||||
|
if (provider_.memory_types_host_coherent() & (uint32_t(1) << memory_type_)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const VulkanProvider::DeviceFunctions& dfn = provider_.dfn();
|
||||||
|
VkDevice device = provider_.device();
|
||||||
|
VkMappedMemoryRange range;
|
||||||
|
range.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
||||||
|
range.pNext = nullptr;
|
||||||
|
range.memory = static_cast<const VulkanPage*>(page)->memory_;
|
||||||
|
range.offset = VkDeviceSize(offset);
|
||||||
|
range.size = VkDeviceSize(size);
|
||||||
|
VkDeviceSize non_coherent_atom_size =
|
||||||
|
provider_.device_properties().limits.nonCoherentAtomSize;
|
||||||
|
// On some Android implementations, nonCoherentAtomSize is 0, not 1.
|
||||||
|
if (non_coherent_atom_size > 1) {
|
||||||
|
VkDeviceSize end =
|
||||||
|
xe::round_up(range.offset + range.size, non_coherent_atom_size);
|
||||||
|
range.offset =
|
||||||
|
range.offset / non_coherent_atom_size * non_coherent_atom_size;
|
||||||
|
range.size = end - range.offset;
|
||||||
|
}
|
||||||
|
dfn.vkFlushMappedMemoryRanges(device, 1, &range);
|
||||||
|
}
|
||||||
|
|
||||||
|
VulkanUploadBufferPool::VulkanPage::~VulkanPage() {
|
||||||
|
const VulkanProvider::DeviceFunctions& dfn = provider_.dfn();
|
||||||
|
VkDevice device = provider_.device();
|
||||||
|
dfn.vkDestroyBuffer(device, buffer_, nullptr);
|
||||||
|
// Unmapping is done implicitly when the memory is freed.
|
||||||
|
dfn.vkFreeMemory(device, memory_, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vulkan
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace xe
|
|
@ -0,0 +1,67 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_UI_VULKAN_VULKAN_UPLOAD_BUFFER_POOL_H_
|
||||||
|
#define XENIA_UI_VULKAN_VULKAN_UPLOAD_BUFFER_POOL_H_
|
||||||
|
|
||||||
|
#include "xenia/ui/graphics_upload_buffer_pool.h"
|
||||||
|
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace ui {
|
||||||
|
namespace vulkan {
|
||||||
|
|
||||||
|
class VulkanUploadBufferPool : public GraphicsUploadBufferPool {
|
||||||
|
public:
|
||||||
|
VulkanUploadBufferPool(const VulkanProvider& provider,
|
||||||
|
VkBufferUsageFlags usage,
|
||||||
|
size_t page_size = kDefaultPageSize);
|
||||||
|
|
||||||
|
uint8_t* Request(uint64_t submission_index, size_t size, size_t alignment,
|
||||||
|
VkBuffer& buffer_out, VkDeviceSize& offset_out);
|
||||||
|
uint8_t* RequestPartial(uint64_t submission_index, size_t size,
|
||||||
|
size_t alignment, VkBuffer& buffer_out,
|
||||||
|
VkDeviceSize& offset_out, VkDeviceSize& size_out);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Page* CreatePageImplementation() override;
|
||||||
|
|
||||||
|
void FlushPageWrites(Page* page, size_t offset, size_t size) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct VulkanPage : public Page {
|
||||||
|
// Takes ownership of the buffer and its memory and mapping.
|
||||||
|
VulkanPage(const VulkanProvider& provider, VkBuffer buffer,
|
||||||
|
VkDeviceMemory memory, void* mapping)
|
||||||
|
: provider_(provider),
|
||||||
|
buffer_(buffer),
|
||||||
|
memory_(memory),
|
||||||
|
mapping_(mapping) {}
|
||||||
|
~VulkanPage() override;
|
||||||
|
const VulkanProvider& provider_;
|
||||||
|
VkBuffer buffer_;
|
||||||
|
VkDeviceMemory memory_;
|
||||||
|
void* mapping_;
|
||||||
|
};
|
||||||
|
|
||||||
|
const VulkanProvider& provider_;
|
||||||
|
|
||||||
|
VkDeviceSize allocation_size_;
|
||||||
|
static constexpr uint32_t kMemoryTypeUnknown = UINT32_MAX;
|
||||||
|
static constexpr uint32_t kMemoryTypeUnavailable = kMemoryTypeUnknown - 1;
|
||||||
|
uint32_t memory_type_ = UINT32_MAX;
|
||||||
|
|
||||||
|
VkBufferUsageFlags usage_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace vulkan
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif // XENIA_UI_VULKAN_VULKAN_UPLOAD_BUFFER_POOL_H_
|
|
@ -2,7 +2,7 @@
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Copyright 2019 Ben Vanik. All rights reserved. *
|
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
@ -37,6 +37,22 @@ inline bool DestroyAndNullHandle(F* destroy_function, P parent, T& handle) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline VkShaderModule CreateShaderModule(const VulkanProvider& provider,
|
||||||
|
const void* code, size_t code_size) {
|
||||||
|
VkShaderModuleCreateInfo shader_module_create_info;
|
||||||
|
shader_module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||||
|
shader_module_create_info.pNext = nullptr;
|
||||||
|
shader_module_create_info.flags = 0;
|
||||||
|
shader_module_create_info.codeSize = code_size;
|
||||||
|
shader_module_create_info.pCode = reinterpret_cast<const uint32_t*>(code);
|
||||||
|
VkShaderModule shader_module;
|
||||||
|
return provider.dfn().vkCreateShaderModule(
|
||||||
|
provider.device(), &shader_module_create_info, nullptr,
|
||||||
|
&shader_module) == VK_SUCCESS
|
||||||
|
? shader_module
|
||||||
|
: nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
} // namespace vulkan
|
} // namespace vulkan
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "xenia/base/main.h"
|
||||||
|
#include "xenia/ui/vulkan/vulkan_provider.h"
|
||||||
|
#include "xenia/ui/window.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
int window_demo_main(const std::vector<std::string>& args);
|
||||||
|
|
||||||
|
std::unique_ptr<GraphicsProvider> CreateDemoGraphicsProvider(Window* window) {
|
||||||
|
return xe::ui::vulkan::VulkanProvider::Create(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
DEFINE_ENTRY_POINT("xenia-ui-window-vulkan-demo", xe::ui::window_demo_main, "");
|
|
@ -689,7 +689,6 @@ class GenSpirvCommand(Command):
|
||||||
vulkan_bin_path = os.path.join(vulkan_sdk_path, 'bin')
|
vulkan_bin_path = os.path.join(vulkan_sdk_path, 'bin')
|
||||||
glslang = os.path.join(vulkan_bin_path, 'glslangValidator')
|
glslang = os.path.join(vulkan_bin_path, 'glslangValidator')
|
||||||
spirv_dis = os.path.join(vulkan_bin_path, 'spirv-dis')
|
spirv_dis = os.path.join(vulkan_bin_path, 'spirv-dis')
|
||||||
spirv_remap = os.path.join(vulkan_bin_path, 'spirv-remap')
|
|
||||||
|
|
||||||
# Ensure we have the tools.
|
# Ensure we have the tools.
|
||||||
if not os.path.exists(vulkan_sdk_path):
|
if not os.path.exists(vulkan_sdk_path):
|
||||||
|
@ -701,9 +700,6 @@ class GenSpirvCommand(Command):
|
||||||
elif not has_bin(spirv_dis):
|
elif not has_bin(spirv_dis):
|
||||||
print('ERROR: could not find spirv-dis')
|
print('ERROR: could not find spirv-dis')
|
||||||
return 1
|
return 1
|
||||||
elif not has_bin(spirv_remap):
|
|
||||||
print('ERROR: could not find spirv-remap')
|
|
||||||
return 1
|
|
||||||
|
|
||||||
src_files = [os.path.join(root, name)
|
src_files = [os.path.join(root, name)
|
||||||
for root, dirs, files in os.walk('src')
|
for root, dirs, files in os.walk('src')
|
||||||
|
@ -717,7 +713,8 @@ class GenSpirvCommand(Command):
|
||||||
src_name = os.path.splitext(os.path.basename(src_file))[0]
|
src_name = os.path.splitext(os.path.basename(src_file))[0]
|
||||||
identifier = os.path.basename(src_file).replace('.', '_')
|
identifier = os.path.basename(src_file).replace('.', '_')
|
||||||
|
|
||||||
bin_path = os.path.join(os.path.dirname(src_file), 'bin')
|
bin_path = os.path.join(os.path.dirname(src_file),
|
||||||
|
'bytecode/vulkan_spirv')
|
||||||
spv_file = os.path.join(bin_path, identifier) + '.spv'
|
spv_file = os.path.join(bin_path, identifier) + '.spv'
|
||||||
txt_file = os.path.join(bin_path, identifier) + '.txt'
|
txt_file = os.path.join(bin_path, identifier) + '.txt'
|
||||||
h_file = os.path.join(bin_path, identifier) + '.h'
|
h_file = os.path.join(bin_path, identifier) + '.h'
|
||||||
|
|
Loading…
Reference in New Issue