[D3D12] Draw calls
This commit is contained in:
parent
bb045cae70
commit
5d0ad2e465
|
@ -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) {
|
||||
|
|
|
@ -198,6 +198,9 @@ class D3D12CommandProcessor : public CommandProcessor {
|
|||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_pixel_float_constants_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_fetch_constants_;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_shared_memory_;
|
||||
|
||||
// Current primitive topology.
|
||||
D3D_PRIMITIVE_TOPOLOGY primitive_topology_;
|
||||
};
|
||||
|
||||
} // namespace d3d12
|
||||
|
|
|
@ -168,13 +168,14 @@ std::vector<uint8_t> HlslShaderTranslator::CompleteTranslation() {
|
|||
source.Append(
|
||||
"cbuffer xe_system_constants : register(b0) {\n"
|
||||
" float3 xe_mul_rcp_w;\n"
|
||||
" uint xe_vertex_index_endian;\n"
|
||||
" uint xe_vertex_base_index;\n"
|
||||
" float3 xe_ndc_scale;\n"
|
||||
" uint xe_textures_are_3d;\n"
|
||||
" uint xe_vertex_index_endian;\n"
|
||||
" float3 xe_ndc_offset;\n"
|
||||
" float xe_pixel_half_pixel_offset;\n"
|
||||
" float2 xe_ssaa_inv_scale;\n"
|
||||
" uint xe_pixel_pos_reg;\n"
|
||||
" uint xe_textures_are_3d;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"cbuffer xe_loop_bool_constants : register(b1) {\n"
|
||||
|
@ -229,7 +230,8 @@ std::vector<uint8_t> HlslShaderTranslator::CompleteTranslation() {
|
|||
"XeVertexShaderOutput main(uint xe_vertex_index_be : SV_VertexID) {\n"
|
||||
" float4 xe_r[%u];\n"
|
||||
" uint xe_vertex_index =\n"
|
||||
" XeByteSwap(xe_vertex_index_be, xe_vertex_index_endian);\n"
|
||||
" XeByteSwap(xe_vertex_index_be, xe_vertex_index_endian) +\n"
|
||||
" xe_vertex_base_index;\n"
|
||||
" uint4 xe_vertex_element;\n"
|
||||
" xe_r[0].r = float(xe_vertex_index);\n"
|
||||
" XeVertexShaderOutput xe_output;\n"
|
||||
|
|
|
@ -27,16 +27,17 @@ class HlslShaderTranslator : public ShaderTranslator {
|
|||
struct SystemConstants {
|
||||
// vec4 0
|
||||
float mul_rcp_w[3];
|
||||
uint32_t vertex_index_endian;
|
||||
uint32_t vertex_base_index;
|
||||
// vec4 1
|
||||
float ndc_scale[3];
|
||||
uint32_t textures_are_3d;
|
||||
uint32_t vertex_index_endian;
|
||||
// vec4 2
|
||||
float ndc_offset[3];
|
||||
float pixel_half_pixel_offset;
|
||||
// vec4 3
|
||||
float ssaa_inv_scale[2];
|
||||
uint32_t pixel_pos_reg;
|
||||
uint32_t textures_are_3d;
|
||||
};
|
||||
|
||||
enum class SRVType : uint32_t {
|
||||
|
|
|
@ -88,7 +88,7 @@ uint8_t* UploadBufferPool::RequestFull(
|
|||
if (current_gpu_address_ == 0) {
|
||||
current_gpu_address_ = unsent_->buffer->GetGPUVirtualAddress();
|
||||
}
|
||||
*gpu_address_out = current_gpu_address_ = current_size_;
|
||||
*gpu_address_out = current_gpu_address_ + current_size_;
|
||||
}
|
||||
uint8_t* mapping = current_mapping_ + current_size_;
|
||||
current_size_ += size;
|
||||
|
@ -118,7 +118,7 @@ uint8_t* UploadBufferPool::RequestPartial(
|
|||
if (current_gpu_address_ == 0) {
|
||||
current_gpu_address_ = unsent_->buffer->GetGPUVirtualAddress();
|
||||
}
|
||||
*gpu_address_out = current_gpu_address_ = current_size_;
|
||||
*gpu_address_out = current_gpu_address_ + current_size_;
|
||||
}
|
||||
uint8_t* mapping = current_mapping_ + current_size_;
|
||||
current_size_ += size;
|
||||
|
|
Loading…
Reference in New Issue