early-access version 3838
This commit is contained in:
parent
c807f0cfc8
commit
d6da91ca90
16 changed files with 144 additions and 22 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 3837.
|
This is the source code for early-access 3838.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -161,7 +161,8 @@ enum class SpecialRegister : u64 {
|
||||||
LOG_WARNING(Shader, "(STUBBED) SR_AFFINITY");
|
LOG_WARNING(Shader, "(STUBBED) SR_AFFINITY");
|
||||||
return ir.Imm32(0); // This is the default value hardware returns.
|
return ir.Imm32(0); // This is the default value hardware returns.
|
||||||
default:
|
default:
|
||||||
throw NotImplementedException("S2R special register {}", special_register);
|
LOG_CRITICAL(Shader, "(STUBBED) Special register {}", special_register);
|
||||||
|
return ir.Imm32(0); // This is the default value hardware returns.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
|
@ -295,8 +295,11 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer(
|
||||||
MarkWrittenBuffer(buffer_id, cpu_addr, size);
|
MarkWrittenBuffer(buffer_id, cpu_addr, size);
|
||||||
break;
|
break;
|
||||||
case ObtainBufferOperation::DiscardWrite: {
|
case ObtainBufferOperation::DiscardWrite: {
|
||||||
IntervalType interval{cpu_addr, size};
|
VAddr cpu_addr_start = Common::AlignDown(cpu_addr, 64);
|
||||||
|
VAddr cpu_addr_end = Common::AlignUp(cpu_addr + size, 64);
|
||||||
|
IntervalType interval{cpu_addr_start, cpu_addr_end};
|
||||||
ClearDownload(interval);
|
ClearDownload(interval);
|
||||||
|
common_ranges.subtract(interval);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -1165,6 +1168,11 @@ void BufferCache<P>::UpdateDrawIndirect() {
|
||||||
.size = static_cast<u32>(size),
|
.size = static_cast<u32>(size),
|
||||||
.buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)),
|
.buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)),
|
||||||
};
|
};
|
||||||
|
VAddr cpu_addr_start = Common::AlignDown(*cpu_addr, 64);
|
||||||
|
VAddr cpu_addr_end = Common::AlignUp(*cpu_addr + size, 64);
|
||||||
|
IntervalType interval{cpu_addr_start, cpu_addr_end};
|
||||||
|
ClearDownload(interval);
|
||||||
|
common_ranges.subtract(interval);
|
||||||
};
|
};
|
||||||
if (current_draw_indirect->include_count) {
|
if (current_draw_indirect->include_count) {
|
||||||
update(current_draw_indirect->count_start_address, sizeof(u32),
|
update(current_draw_indirect->count_start_address, sizeof(u32),
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
|
|
||||||
constexpr u32 MacroRegistersStart = 0xE00;
|
constexpr u32 MacroRegistersStart = 0xE00;
|
||||||
|
constexpr u32 ComputeInline = 0x6D;
|
||||||
|
|
||||||
DmaPusher::DmaPusher(Core::System& system_, GPU& gpu_, MemoryManager& memory_manager_,
|
DmaPusher::DmaPusher(Core::System& system_, GPU& gpu_, MemoryManager& memory_manager_,
|
||||||
Control::ChannelState& channel_state_)
|
Control::ChannelState& channel_state_)
|
||||||
|
@ -83,20 +84,35 @@ bool DmaPusher::Step() {
|
||||||
dma_state.dma_get, command_list_header.size * sizeof(u32));
|
dma_state.dma_get, command_list_header.size * sizeof(u32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Settings::IsGPULevelHigh() && dma_state.method < MacroRegistersStart) {
|
const auto safe_process = [&] {
|
||||||
Core::Memory::GpuGuestMemory<Tegra::CommandHeader,
|
Core::Memory::GpuGuestMemory<Tegra::CommandHeader,
|
||||||
Core::Memory::GuestMemoryFlags::SafeRead>
|
Core::Memory::GuestMemoryFlags::SafeRead>
|
||||||
headers(memory_manager, dma_state.dma_get, command_list_header.size,
|
headers(memory_manager, dma_state.dma_get, command_list_header.size,
|
||||||
&command_headers);
|
&command_headers);
|
||||||
ProcessCommands(headers);
|
ProcessCommands(headers);
|
||||||
return true;
|
};
|
||||||
}
|
const auto unsafe_process = [&] {
|
||||||
Core::Memory::GpuGuestMemory<Tegra::CommandHeader,
|
Core::Memory::GpuGuestMemory<Tegra::CommandHeader,
|
||||||
Core::Memory::GuestMemoryFlags::UnsafeRead>
|
Core::Memory::GuestMemoryFlags::UnsafeRead>
|
||||||
headers(memory_manager, dma_state.dma_get, command_list_header.size, &command_headers);
|
headers(memory_manager, dma_state.dma_get, command_list_header.size,
|
||||||
|
&command_headers);
|
||||||
ProcessCommands(headers);
|
ProcessCommands(headers);
|
||||||
|
};
|
||||||
|
if (Settings::IsGPULevelHigh()) {
|
||||||
|
if (dma_state.method >= MacroRegistersStart) {
|
||||||
|
unsafe_process();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (subchannel_type[dma_state.subchannel] == Engines::EngineTypes::KeplerCompute &&
|
||||||
|
dma_state.method == ComputeInline) {
|
||||||
|
unsafe_process();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
safe_process();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
unsafe_process();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,8 +130,10 @@ public:
|
||||||
|
|
||||||
void DispatchCalls();
|
void DispatchCalls();
|
||||||
|
|
||||||
void BindSubchannel(Engines::EngineInterface* engine, u32 subchannel_id) {
|
void BindSubchannel(Engines::EngineInterface* engine, u32 subchannel_id,
|
||||||
|
Engines::EngineTypes engine_type) {
|
||||||
subchannels[subchannel_id] = engine;
|
subchannels[subchannel_id] = engine;
|
||||||
|
subchannel_type[subchannel_id] = engine_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
|
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
|
||||||
|
@ -170,6 +172,7 @@ private:
|
||||||
const bool ib_enable{true}; ///< IB mode enabled
|
const bool ib_enable{true}; ///< IB mode enabled
|
||||||
|
|
||||||
std::array<Engines::EngineInterface*, max_subchannels> subchannels{};
|
std::array<Engines::EngineInterface*, max_subchannels> subchannels{};
|
||||||
|
std::array<Engines::EngineTypes, max_subchannels> subchannel_type;
|
||||||
|
|
||||||
GPU& gpu;
|
GPU& gpu;
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
|
@ -11,6 +11,14 @@
|
||||||
|
|
||||||
namespace Tegra::Engines {
|
namespace Tegra::Engines {
|
||||||
|
|
||||||
|
enum class EngineTypes : u32 {
|
||||||
|
KeplerCompute,
|
||||||
|
Maxwell3D,
|
||||||
|
Fermi2D,
|
||||||
|
MaxwellDMA,
|
||||||
|
KeplerMemory,
|
||||||
|
};
|
||||||
|
|
||||||
class EngineInterface {
|
class EngineInterface {
|
||||||
public:
|
public:
|
||||||
virtual ~EngineInterface() = default;
|
virtual ~EngineInterface() = default;
|
||||||
|
|
|
@ -69,6 +69,14 @@ public:
|
||||||
/// Binds a rasterizer to this engine.
|
/// Binds a rasterizer to this engine.
|
||||||
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
|
void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
|
||||||
|
|
||||||
|
GPUVAddr ExecTargetAddress() const {
|
||||||
|
return regs.dest.Address();
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetUploadSize() const {
|
||||||
|
return copy_size;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ProcessData(std::span<const u8> read_buffer);
|
void ProcessData(std::span<const u8> read_buffer);
|
||||||
|
|
||||||
|
|
|
@ -43,16 +43,33 @@ void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_cal
|
||||||
|
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case KEPLER_COMPUTE_REG_INDEX(exec_upload): {
|
case KEPLER_COMPUTE_REG_INDEX(exec_upload): {
|
||||||
|
UploadInfo info{.upload_address = upload_address,
|
||||||
|
.exec_address = upload_state.ExecTargetAddress(),
|
||||||
|
.copy_size = upload_state.GetUploadSize()};
|
||||||
|
uploads.push_back(info);
|
||||||
upload_state.ProcessExec(regs.exec_upload.linear != 0);
|
upload_state.ProcessExec(regs.exec_upload.linear != 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KEPLER_COMPUTE_REG_INDEX(data_upload): {
|
case KEPLER_COMPUTE_REG_INDEX(data_upload): {
|
||||||
|
upload_address = current_dma_segment;
|
||||||
upload_state.ProcessData(method_argument, is_last_call);
|
upload_state.ProcessData(method_argument, is_last_call);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case KEPLER_COMPUTE_REG_INDEX(launch):
|
case KEPLER_COMPUTE_REG_INDEX(launch): {
|
||||||
|
const GPUVAddr launch_desc_loc = regs.launch_desc_loc.Address();
|
||||||
|
|
||||||
|
for (auto& data : uploads) {
|
||||||
|
const GPUVAddr offset = data.exec_address - launch_desc_loc;
|
||||||
|
if (offset / sizeof(u32) == LAUNCH_REG_INDEX(grid_dim_x) &&
|
||||||
|
memory_manager.IsMemoryDirty(data.upload_address, data.copy_size)) {
|
||||||
|
indirect_compute = {data.upload_address};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uploads.clear();
|
||||||
ProcessLaunch();
|
ProcessLaunch();
|
||||||
|
indirect_compute = std::nullopt;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -62,6 +79,7 @@ void KeplerCompute::CallMultiMethod(u32 method, const u32* base_start, u32 amoun
|
||||||
u32 methods_pending) {
|
u32 methods_pending) {
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case KEPLER_COMPUTE_REG_INDEX(data_upload):
|
case KEPLER_COMPUTE_REG_INDEX(data_upload):
|
||||||
|
upload_address = current_dma_segment;
|
||||||
upload_state.ProcessData(base_start, amount);
|
upload_state.ProcessData(base_start, amount);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
|
@ -36,6 +37,9 @@ namespace Tegra::Engines {
|
||||||
#define KEPLER_COMPUTE_REG_INDEX(field_name) \
|
#define KEPLER_COMPUTE_REG_INDEX(field_name) \
|
||||||
(offsetof(Tegra::Engines::KeplerCompute::Regs, field_name) / sizeof(u32))
|
(offsetof(Tegra::Engines::KeplerCompute::Regs, field_name) / sizeof(u32))
|
||||||
|
|
||||||
|
#define LAUNCH_REG_INDEX(field_name) \
|
||||||
|
(offsetof(Tegra::Engines::KeplerCompute::LaunchParams, field_name) / sizeof(u32))
|
||||||
|
|
||||||
class KeplerCompute final : public EngineInterface {
|
class KeplerCompute final : public EngineInterface {
|
||||||
public:
|
public:
|
||||||
explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager);
|
explicit KeplerCompute(Core::System& system, MemoryManager& memory_manager);
|
||||||
|
@ -201,6 +205,10 @@ public:
|
||||||
void CallMultiMethod(u32 method, const u32* base_start, u32 amount,
|
void CallMultiMethod(u32 method, const u32* base_start, u32 amount,
|
||||||
u32 methods_pending) override;
|
u32 methods_pending) override;
|
||||||
|
|
||||||
|
std::optional<GPUVAddr> GetIndirectComputeAddress() const {
|
||||||
|
return indirect_compute;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ProcessLaunch();
|
void ProcessLaunch();
|
||||||
|
|
||||||
|
@ -216,6 +224,15 @@ private:
|
||||||
MemoryManager& memory_manager;
|
MemoryManager& memory_manager;
|
||||||
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||||
Upload::State upload_state;
|
Upload::State upload_state;
|
||||||
|
GPUVAddr upload_address;
|
||||||
|
|
||||||
|
struct UploadInfo {
|
||||||
|
GPUVAddr upload_address;
|
||||||
|
GPUVAddr exec_address;
|
||||||
|
u32 copy_size;
|
||||||
|
};
|
||||||
|
std::vector<UploadInfo> uploads;
|
||||||
|
std::optional<GPUVAddr> indirect_compute{};
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ASSERT_REG_POSITION(field_name, position) \
|
#define ASSERT_REG_POSITION(field_name, position) \
|
||||||
|
|
|
@ -34,19 +34,24 @@ void Puller::ProcessBindMethod(const MethodCall& method_call) {
|
||||||
bound_engines[method_call.subchannel] = engine_id;
|
bound_engines[method_call.subchannel] = engine_id;
|
||||||
switch (engine_id) {
|
switch (engine_id) {
|
||||||
case EngineID::FERMI_TWOD_A:
|
case EngineID::FERMI_TWOD_A:
|
||||||
dma_pusher.BindSubchannel(channel_state.fermi_2d.get(), method_call.subchannel);
|
dma_pusher.BindSubchannel(channel_state.fermi_2d.get(), method_call.subchannel,
|
||||||
|
EngineTypes::Fermi2D);
|
||||||
break;
|
break;
|
||||||
case EngineID::MAXWELL_B:
|
case EngineID::MAXWELL_B:
|
||||||
dma_pusher.BindSubchannel(channel_state.maxwell_3d.get(), method_call.subchannel);
|
dma_pusher.BindSubchannel(channel_state.maxwell_3d.get(), method_call.subchannel,
|
||||||
|
EngineTypes::Maxwell3D);
|
||||||
break;
|
break;
|
||||||
case EngineID::KEPLER_COMPUTE_B:
|
case EngineID::KEPLER_COMPUTE_B:
|
||||||
dma_pusher.BindSubchannel(channel_state.kepler_compute.get(), method_call.subchannel);
|
dma_pusher.BindSubchannel(channel_state.kepler_compute.get(), method_call.subchannel,
|
||||||
|
EngineTypes::KeplerCompute);
|
||||||
break;
|
break;
|
||||||
case EngineID::MAXWELL_DMA_COPY_A:
|
case EngineID::MAXWELL_DMA_COPY_A:
|
||||||
dma_pusher.BindSubchannel(channel_state.maxwell_dma.get(), method_call.subchannel);
|
dma_pusher.BindSubchannel(channel_state.maxwell_dma.get(), method_call.subchannel,
|
||||||
|
EngineTypes::MaxwellDMA);
|
||||||
break;
|
break;
|
||||||
case EngineID::KEPLER_INLINE_TO_MEMORY_B:
|
case EngineID::KEPLER_INLINE_TO_MEMORY_B:
|
||||||
dma_pusher.BindSubchannel(channel_state.kepler_memory.get(), method_call.subchannel);
|
dma_pusher.BindSubchannel(channel_state.kepler_memory.get(), method_call.subchannel,
|
||||||
|
EngineTypes::KeplerMemory);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED_MSG("Unimplemented engine {:04X}", engine_id);
|
UNIMPLEMENTED_MSG("Unimplemented engine {:04X}", engine_id);
|
||||||
|
|
|
@ -380,6 +380,17 @@ void RasterizerOpenGL::DispatchCompute() {
|
||||||
pipeline->SetEngine(kepler_compute, gpu_memory);
|
pipeline->SetEngine(kepler_compute, gpu_memory);
|
||||||
pipeline->Configure();
|
pipeline->Configure();
|
||||||
const auto& qmd{kepler_compute->launch_description};
|
const auto& qmd{kepler_compute->launch_description};
|
||||||
|
auto indirect_address = kepler_compute->GetIndirectComputeAddress();
|
||||||
|
if (indirect_address) {
|
||||||
|
// DispatchIndirect
|
||||||
|
static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize;
|
||||||
|
const auto post_op = VideoCommon::ObtainBufferOperation::DiscardWrite;
|
||||||
|
const auto [buffer, offset] =
|
||||||
|
buffer_cache.ObtainBuffer(*indirect_address, 12, sync_info, post_op);
|
||||||
|
glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER, buffer->Handle());
|
||||||
|
glDispatchComputeIndirect(static_cast<GLintptr>(offset));
|
||||||
|
return;
|
||||||
|
}
|
||||||
glDispatchCompute(qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z);
|
glDispatchCompute(qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z);
|
||||||
++num_queued_commands;
|
++num_queued_commands;
|
||||||
has_written_global_memory |= pipeline->WritesGlobalMemory();
|
has_written_global_memory |= pipeline->WritesGlobalMemory();
|
||||||
|
|
|
@ -665,6 +665,19 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
|
||||||
std::move(modules), infos);
|
std::move(modules), infos);
|
||||||
|
|
||||||
} catch (const Shader::Exception& exception) {
|
} catch (const Shader::Exception& exception) {
|
||||||
|
auto hash = key.Hash();
|
||||||
|
size_t env_index{0};
|
||||||
|
for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
|
||||||
|
if (key.unique_hashes[index] == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Shader::Environment& env{*envs[env_index]};
|
||||||
|
++env_index;
|
||||||
|
|
||||||
|
const u32 cfg_offset{static_cast<u32>(env.StartAddress() + sizeof(Shader::ProgramHeader))};
|
||||||
|
Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset, index == 0);
|
||||||
|
env.Dump(hash, key.unique_hashes[index]);
|
||||||
|
}
|
||||||
LOG_ERROR(Render_Vulkan, "{}", exception.what());
|
LOG_ERROR(Render_Vulkan, "{}", exception.what());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -456,6 +456,20 @@ void RasterizerVulkan::DispatchCompute() {
|
||||||
pipeline->Configure(*kepler_compute, *gpu_memory, scheduler, buffer_cache, texture_cache);
|
pipeline->Configure(*kepler_compute, *gpu_memory, scheduler, buffer_cache, texture_cache);
|
||||||
|
|
||||||
const auto& qmd{kepler_compute->launch_description};
|
const auto& qmd{kepler_compute->launch_description};
|
||||||
|
auto indirect_address = kepler_compute->GetIndirectComputeAddress();
|
||||||
|
if (indirect_address) {
|
||||||
|
// DispatchIndirect
|
||||||
|
static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize;
|
||||||
|
const auto post_op = VideoCommon::ObtainBufferOperation::DiscardWrite;
|
||||||
|
const auto [buffer, offset] =
|
||||||
|
buffer_cache.ObtainBuffer(*indirect_address, 12, sync_info, post_op);
|
||||||
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
|
scheduler.Record([indirect_buffer = buffer->Handle(),
|
||||||
|
indirect_offset = offset](vk::CommandBuffer cmdbuf) {
|
||||||
|
cmdbuf.DispatchIndirect(indirect_buffer, indirect_offset);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z};
|
const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z};
|
||||||
scheduler.RequestOutsideRenderPassOperationContext();
|
scheduler.RequestOutsideRenderPassOperationContext();
|
||||||
scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); });
|
scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); });
|
||||||
|
|
|
@ -1193,12 +1193,6 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
|
||||||
const VkImageAspectFlags aspect_mask = dst.AspectMask();
|
const VkImageAspectFlags aspect_mask = dst.AspectMask();
|
||||||
ASSERT(aspect_mask == src.AspectMask());
|
ASSERT(aspect_mask == src.AspectMask());
|
||||||
|
|
||||||
if (VideoCore::Surface::BytesPerBlock(src.info.format) !=
|
|
||||||
VideoCore::Surface::BytesPerBlock(dst.info.format)) {
|
|
||||||
ReinterpretImage(dst, src, copies);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ranges::transform(copies, vk_copies.begin(), [aspect_mask](const auto& copy) {
|
std::ranges::transform(copies, vk_copies.begin(), [aspect_mask](const auto& copy) {
|
||||||
return MakeImageCopy(copy, aspect_mask);
|
return MakeImageCopy(copy, aspect_mask);
|
||||||
});
|
});
|
||||||
|
|
|
@ -94,6 +94,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
|
||||||
X(vkCmdCopyImageToBuffer);
|
X(vkCmdCopyImageToBuffer);
|
||||||
X(vkCmdCopyQueryPoolResults);
|
X(vkCmdCopyQueryPoolResults);
|
||||||
X(vkCmdDispatch);
|
X(vkCmdDispatch);
|
||||||
|
X(vkCmdDispatchIndirect);
|
||||||
X(vkCmdDraw);
|
X(vkCmdDraw);
|
||||||
X(vkCmdDrawIndexed);
|
X(vkCmdDrawIndexed);
|
||||||
X(vkCmdDrawIndirect);
|
X(vkCmdDrawIndirect);
|
||||||
|
|
|
@ -205,6 +205,7 @@ struct DeviceDispatch : InstanceDispatch {
|
||||||
PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer{};
|
PFN_vkCmdCopyImageToBuffer vkCmdCopyImageToBuffer{};
|
||||||
PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults{};
|
PFN_vkCmdCopyQueryPoolResults vkCmdCopyQueryPoolResults{};
|
||||||
PFN_vkCmdDispatch vkCmdDispatch{};
|
PFN_vkCmdDispatch vkCmdDispatch{};
|
||||||
|
PFN_vkCmdDispatchIndirect vkCmdDispatchIndirect{};
|
||||||
PFN_vkCmdDraw vkCmdDraw{};
|
PFN_vkCmdDraw vkCmdDraw{};
|
||||||
PFN_vkCmdDrawIndexed vkCmdDrawIndexed{};
|
PFN_vkCmdDrawIndexed vkCmdDrawIndexed{};
|
||||||
PFN_vkCmdDrawIndirect vkCmdDrawIndirect{};
|
PFN_vkCmdDrawIndirect vkCmdDrawIndirect{};
|
||||||
|
@ -1220,6 +1221,10 @@ public:
|
||||||
dld->vkCmdDispatch(handle, x, y, z);
|
dld->vkCmdDispatch(handle, x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DispatchIndirect(VkBuffer indirect_buffer, VkDeviceSize offset) const noexcept {
|
||||||
|
dld->vkCmdDispatchIndirect(handle, indirect_buffer, offset);
|
||||||
|
}
|
||||||
|
|
||||||
void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
|
void PipelineBarrier(VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
|
||||||
VkDependencyFlags dependency_flags, Span<VkMemoryBarrier> memory_barriers,
|
VkDependencyFlags dependency_flags, Span<VkMemoryBarrier> memory_barriers,
|
||||||
Span<VkBufferMemoryBarrier> buffer_barriers,
|
Span<VkBufferMemoryBarrier> buffer_barriers,
|
||||||
|
|
Loading…
Reference in a new issue