[D3D12] Draw calls
This commit is contained in:
@@ -481,6 +481,28 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
||||
}
|
||||
|
||||
bool indexed = index_buffer_info != nullptr && index_buffer_info->guest_base;
|
||||
if (indexed && regs[XE_GPU_REG_PA_SU_SC_MODE_CNTL].u32 & (1 << 21)) {
|
||||
uint32_t reset_index = regs[XE_GPU_REG_VGT_MULTI_PRIM_IB_RESET_INDX].u32;
|
||||
uint32_t reset_index_expected;
|
||||
if (index_buffer_info->format == IndexFormat::kInt32) {
|
||||
reset_index_expected = 0xFFFFFFFFu;
|
||||
} else {
|
||||
reset_index_expected = 0xFFFFu;
|
||||
}
|
||||
if (reset_index != reset_index_expected) {
|
||||
// Only 0xFFFF and 0xFFFFFFFF primitive restart indices are supported by
|
||||
// Direct3D 12 (endianness doesn't matter for them). However, Direct3D 9
|
||||
// uses 0xFFFF as the reset index. With shared memory, it's impossible to
|
||||
// replace the cut index in the buffer without affecting the game memory.
|
||||
XELOGE(
|
||||
"The game uses the primitive restart index 0x%X that isn't 0xFFFF or "
|
||||
"0xFFFFFFFF. Report the game to Xenia developers so geometry shaders "
|
||||
"will be added to handle this!",
|
||||
reset_index);
|
||||
assert_always();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Shaders will have already been defined by previous loads.
|
||||
// We need them to do just about anything so validate here.
|
||||
@@ -502,6 +524,29 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
||||
ID3D12GraphicsCommandList* command_list =
|
||||
command_lists_[current_queue_frame_]->GetCommandList();
|
||||
|
||||
// Set the primitive topology.
|
||||
D3D_PRIMITIVE_TOPOLOGY primitive_topology;
|
||||
switch (primitive_type) {
|
||||
case PrimitiveType::kLineList:
|
||||
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
|
||||
break;
|
||||
case PrimitiveType::kLineStrip:
|
||||
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
|
||||
break;
|
||||
case PrimitiveType::kTriangleList:
|
||||
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
break;
|
||||
case PrimitiveType::kTriangleStrip:
|
||||
primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (primitive_topology_ != primitive_topology) {
|
||||
primitive_topology_ = primitive_topology;
|
||||
command_list->IASetPrimitiveTopology(primitive_topology);
|
||||
}
|
||||
|
||||
// Get the pipeline and translate the shaders so used textures are known.
|
||||
ID3D12PipelineState* pipeline;
|
||||
ID3D12RootSignature* root_signature;
|
||||
@@ -532,13 +577,33 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Shared memory test.
|
||||
// Ensure vertex and index buffers are resident and draw.
|
||||
// TODO(Triang3l): Cache residency for ranges in a way similar to how texture
|
||||
// validity will be tracked.
|
||||
shared_memory_->UseForReading(command_list);
|
||||
uint64_t vertex_buffers_resident[2] = {};
|
||||
for (const auto& vertex_binding : vertex_shader->vertex_bindings()) {
|
||||
uint32_t vfetch_index = vertex_binding.fetch_constant;
|
||||
if (vertex_buffers_resident[vfetch_index >> 6] &
|
||||
(1ull << (vfetch_index & 63))) {
|
||||
continue;
|
||||
}
|
||||
uint32_t vfetch_constant_index =
|
||||
XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0 + vfetch_index * 2;
|
||||
uint32_t vfetch_address = regs[vfetch_constant_index].u32 << 2;
|
||||
shared_memory_->UseRange(regs[vfetch_constant_index].u32 << 2,
|
||||
regs[vfetch_constant_index + 1].u32 & 0x3FFFFFC);
|
||||
vertex_buffers_resident[vfetch_index >> 6] |= 1ull << (vfetch_index & 63);
|
||||
}
|
||||
if (indexed) {
|
||||
uint32_t index_size = index_buffer_info->format == IndexFormat::kInt32
|
||||
? sizeof(uint32_t)
|
||||
: sizeof(uint16_t);
|
||||
shared_memory_->UseRange(index_buffer_info->guest_base,
|
||||
index_buffer_info->count * index_size);
|
||||
command_list->DrawIndexedInstanced(index_count, 1, 0, 0, 0);
|
||||
} else {
|
||||
command_list->DrawInstanced(index_count, 1, 0, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -575,10 +640,15 @@ bool D3D12CommandProcessor::BeginFrame() {
|
||||
cbuffer_bindings_fetch_.up_to_date = false;
|
||||
draw_view_full_update_ = 0;
|
||||
draw_sampler_full_update_ = 0;
|
||||
primitive_topology_ = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
||||
|
||||
command_lists_setup_[current_queue_frame_]->BeginRecording();
|
||||
command_lists_[current_queue_frame_]->BeginRecording();
|
||||
|
||||
constant_buffer_pool_->BeginFrame();
|
||||
view_heap_pool_->BeginFrame();
|
||||
sampler_heap_pool_->BeginFrame();
|
||||
|
||||
shared_memory_->BeginFrame();
|
||||
|
||||
return true;
|
||||
@@ -602,6 +672,10 @@ bool D3D12CommandProcessor::EndFrame() {
|
||||
}
|
||||
command_list->Execute();
|
||||
|
||||
sampler_heap_pool_->EndFrame();
|
||||
view_heap_pool_->EndFrame();
|
||||
constant_buffer_pool_->EndFrame();
|
||||
|
||||
auto context = GetD3D12Context();
|
||||
context->EndSwap();
|
||||
current_queue_frame_ = UINT32_MAX;
|
||||
@@ -756,6 +830,7 @@ void D3D12CommandProcessor::UpdateFixedFunctionState(
|
||||
|
||||
void D3D12CommandProcessor::UpdateSystemConstantValues(Endian index_endian) {
|
||||
auto& regs = *register_file_;
|
||||
uint32_t vgt_indx_offset = regs[XE_GPU_REG_VGT_INDX_OFFSET].u32;
|
||||
uint32_t pa_cl_vte_cntl = regs[XE_GPU_REG_PA_CL_VTE_CNTL].u32;
|
||||
uint32_t pa_cl_clip_cntl = regs[XE_GPU_REG_PA_CL_CLIP_CNTL].u32;
|
||||
uint32_t pa_su_vtx_cntl = regs[XE_GPU_REG_PA_SU_VTX_CNTL].u32;
|
||||
@@ -765,6 +840,10 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(Endian index_endian) {
|
||||
|
||||
bool dirty = false;
|
||||
|
||||
// Vertex index offset.
|
||||
dirty |= system_constants_.vertex_base_index != vgt_indx_offset;
|
||||
system_constants_.vertex_base_index = vgt_indx_offset;
|
||||
|
||||
// Index buffer endianness.
|
||||
dirty |= system_constants_.vertex_index_endian != uint32_t(index_endian);
|
||||
system_constants_.vertex_index_endian = uint32_t(index_endian);
|
||||
@@ -966,6 +1045,7 @@ bool D3D12CommandProcessor::UpdateBindings(
|
||||
draw_view_full_update_, view_count_partial_update, view_count_full_update,
|
||||
view_cpu_handle, view_gpu_handle);
|
||||
if (view_full_update_index == 0) {
|
||||
XELOGE("View full update index is 0!");
|
||||
return false;
|
||||
}
|
||||
if (draw_view_full_update_ != view_full_update_index) {
|
||||
|
||||
Reference in New Issue
Block a user