GPUDevice: Combine draw and push constant functions

Prevents us from being in a situation where the push constants haven't
been uploaded because we couldn't allocate a descriptor or something
else which forced a flush.
pull/3605/head
Stenzek 11 months ago
parent 683ccbf216
commit 6848f07c57
No known key found for this signature in database

@ -1128,8 +1128,7 @@ void FullscreenUI::DrawShaderBackgroundCallback(const ImDrawList* parent_list, c
static_cast<float>(Timer::ConvertValueToSeconds(Timer::GetCurrentValue() - s_locals.app_background_load_time));
g_gpu_device->SetPipeline(s_locals.app_background_shader.get());
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
g_gpu_device->Draw(3, 0);
g_gpu_device->DrawWithPushConstants(3, 0, &uniforms, sizeof(uniforms));
}
bool FullscreenUI::LoadBackgroundImage(const std::string& path, Error* error)

@ -825,14 +825,13 @@ void FullscreenUI::RenderTransitionBlend(GPUSwapChain* swap_chain)
g_gpu_device->SetViewportAndScissor(0, 0, swap_chain->GetPostRotatedWidth(), swap_chain->GetPostRotatedHeight());
g_gpu_device->SetTextureSampler(0, curr, g_gpu_device->GetNearestSampler());
g_gpu_device->SetTextureSampler(1, s_state.transition_prev_texture.get(), g_gpu_device->GetNearestSampler());
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
const GSVector2i size = swap_chain->GetSizeVec();
const GSVector2i postrotated_size = swap_chain->GetPostRotatedSizeVec();
const GSVector4 uv_rect = g_gpu_device->UsesLowerLeftOrigin() ? GSVector4::cxpr(0.0f, 1.0f, 1.0f, 0.0f) :
GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f);
GPUPresenter::DrawScreenQuad(GSVector4i::loadh(size), uv_rect, size, postrotated_size, DisplayRotation::Normal,
swap_chain->GetPreRotation());
swap_chain->GetPreRotation(), uniforms, sizeof(uniforms));
}
void FullscreenUI::UpdateTransitionState()

@ -85,8 +85,8 @@ GSVector4 GPUBackend::GetScreenQuadClipSpaceCoordinates(const GSVector4i bounds,
return GSVector4::xyxy(x, y).xzyw();
}
void GPUBackend::DrawScreenQuad(const GSVector4i bounds, const GSVector2i rt_size,
const GSVector4 uv_bounds /* = GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f) */)
void GPUBackend::DrawScreenQuad(const GSVector4i bounds, const GSVector2i rt_size, const GSVector4 uv_bounds,
const void* push_constants, u32 push_constants_size)
{
const GSVector4 xy = GetScreenQuadClipSpaceCoordinates(bounds, rt_size);
@ -101,7 +101,11 @@ void GPUBackend::DrawScreenQuad(const GSVector4i bounds, const GSVector2i rt_siz
vertices[3].Set(xy.zw(), uv_bounds.zw());
g_gpu_device->UnmapVertexBuffer(sizeof(ScreenVertex), 4);
g_gpu_device->Draw(4, base_vertex);
if (push_constants_size > 0)
g_gpu_device->DrawWithPushConstants(4, base_vertex, push_constants, push_constants_size);
else
g_gpu_device->Draw(4, base_vertex);
}
bool GPUBackend::Initialize(bool clear_vram, Error* error)

@ -117,8 +117,8 @@ public:
static void SetScreenQuadInputLayout(GPUPipeline::GraphicsConfig& config);
static GSVector4 GetScreenQuadClipSpaceCoordinates(const GSVector4i bounds, const GSVector2i rt_size);
static void DrawScreenQuad(const GSVector4i bounds, const GSVector2i rt_size,
const GSVector4 uv_bounds = GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f));
static void DrawScreenQuad(const GSVector4i bounds, const GSVector2i rt_size, const GSVector4 uv_bounds,
const void* push_constants, u32 push_constants_size);
protected:
enum : u32

@ -2040,8 +2040,7 @@ void GPU_HW::CopyAndClearDepthBuffer(bool only_drawing_area)
g_gpu_device->SetPipeline(m_copy_depth_pipeline.get());
const float uniforms[4] = {0.0f, 0.0f, 1.0f, 1.0f};
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
g_gpu_device->Draw(3, 0);
g_gpu_device->DrawWithPushConstants(3, 0, uniforms, sizeof(uniforms));
RestoreDeviceContext();
}
@ -2064,12 +2063,12 @@ void GPU_HW::ClearDepthBuffer(bool only_drawing_area)
// need to re-bind for rov, because we can't turn colour writes off for only the first target
if (!m_use_rov_for_shader_blend)
{
DrawScreenQuad(clear_bounds, m_vram_depth_texture->GetSizeVec());
DrawScreenQuad(clear_bounds, m_vram_depth_texture->GetSizeVec(), GSVector4::zero(), nullptr, 0);
}
else
{
g_gpu_device->SetRenderTarget(m_vram_depth_texture.get());
DrawScreenQuad(clear_bounds, m_vram_depth_texture->GetSizeVec());
DrawScreenQuad(clear_bounds, m_vram_depth_texture->GetSizeVec(), GSVector4::zero(), nullptr, 0);
SetVRAMRenderTarget();
}
}
@ -3114,7 +3113,7 @@ bool GPU_HW::BlitVRAMReplacementTexture(GPUTexture* tex, u32 dst_x, u32 dst_y, u
const GSVector4i rect(dst_x, dst_y, dst_x + width, dst_y + height);
g_gpu_device->SetScissor(rect);
DrawScreenQuad(rect, m_vram_texture->GetSizeVec());
DrawScreenQuad(rect, m_vram_texture->GetSizeVec(), GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f), nullptr, 0);
RestoreDeviceContext();
return true;
}
@ -3359,11 +3358,10 @@ void GPU_HW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color, bool inter
GPUDevice::RGBA8ToFloat(m_true_color ? color : VRAMRGBA5551ToRGBA8888(VRAMRGBA8888ToRGBA5551(color)));
uniforms.u_interlaced_displayed_field = active_line_lsb;
std::memset(uniforms.pad, 0, sizeof(uniforms.pad));
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
const GSVector4i scaled_bounds = bounds.mul32l(GSVector4i(m_resolution_scale));
g_gpu_device->SetScissor(scaled_bounds);
DrawScreenQuad(scaled_bounds, m_vram_texture->GetSizeVec());
DrawScreenQuad(scaled_bounds, m_vram_texture->GetSizeVec(), GSVector4::zero(), &uniforms, sizeof(uniforms));
RestoreDeviceContext();
}
@ -3408,8 +3406,7 @@ void GPU_HW::DownloadVRAMFromGPU(u32 x, u32 y, u32 width, u32 height)
g_gpu_device->SetPipeline(m_vram_readback_pipeline.get());
g_gpu_device->SetTextureSampler(0, m_vram_texture.get(), g_gpu_device->GetNearestSampler());
g_gpu_device->SetViewportAndScissor(0, 0, encoded_width, encoded_height);
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
g_gpu_device->Draw(3, 0);
g_gpu_device->DrawWithPushConstants(3, 0, uniforms, sizeof(uniforms));
// Stage the readback and copy it into our shadow buffer.
if (m_vram_readback_download_texture->IsImported())
@ -3532,8 +3529,7 @@ void GPU_HW::UpdateVRAMOnGPU(u32 x, u32 y, u32 width, u32 height, const void* da
else
g_gpu_device->SetTextureBuffer(0, m_vram_upload_buffer.get());
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
DrawScreenQuad(scaled_bounds, m_vram_texture->GetSizeVec());
DrawScreenQuad(scaled_bounds, m_vram_texture->GetSizeVec(), GSVector4::zero(), &uniforms, sizeof(uniforms));
RestoreDeviceContext();
}
@ -3610,11 +3606,11 @@ void GPU_HW::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32
// VRAM read texture should already be bound.
g_gpu_device->SetPipeline(m_vram_copy_pipelines[BoolToUInt8(check_mask && m_write_mask_as_depth)].get());
g_gpu_device->SetTextureSampler(0, m_vram_read_texture.get(), g_gpu_device->GetNearestSampler());
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
const GSVector4i dst_bounds_scaled = dst_bounds.mul32l(GSVector4i(m_resolution_scale));
g_gpu_device->SetScissor(dst_bounds_scaled);
DrawScreenQuad(dst_bounds_scaled, m_vram_texture->GetSizeVec());
DrawScreenQuad(dst_bounds_scaled, m_vram_texture->GetSizeVec(), GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f), &uniforms,
sizeof(uniforms));
RestoreDeviceContext();
if (check_mask && !m_pgxp_depth_buffer)
@ -4060,9 +4056,7 @@ void GPU_HW::UpdateDisplay(const GPUBackendUpdateDisplayCommand* cmd)
};
const ExtractUniforms uniforms = {reinterpret_start_x, scaled_vram_offset_y, static_cast<float>(skip_x),
static_cast<float>(line_skip ? 2 : 1)};
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
g_gpu_device->Draw(3, 0);
g_gpu_device->DrawWithPushConstants(3, 0, &uniforms, sizeof(uniforms));
m_vram_extract_texture->MakeReadyForSampling();
if (depth_source)
@ -4216,8 +4210,7 @@ void GPU_HW::DownsampleFramebufferAdaptive(GPUTexture* source, u32 left, u32 top
g_gpu_device->SetRenderTarget(m_downsample_texture.get());
g_gpu_device->SetViewportAndScissor(GSVector4i(0, 0, level_width, level_height));
g_gpu_device->SetPipeline(m_downsample_pass_pipeline.get());
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
g_gpu_device->Draw(3, 0);
g_gpu_device->DrawWithPushConstants(3, 0, &uniforms, sizeof(uniforms));
g_gpu_device->CopyTextureRegion(level_texture.get(), 0, 0, 0, level, m_downsample_texture.get(), 0, 0, 0, 0,
level_width, level_height);
}
@ -4245,8 +4238,7 @@ void GPU_HW::DownsampleFramebufferAdaptive(GPUTexture* source, u32 left, u32 top
g_gpu_device->SetTextureSampler(0, m_downsample_texture.get(), g_gpu_device->GetNearestSampler());
g_gpu_device->SetViewportAndScissor(GSVector4i(0, 0, last_width, last_height));
g_gpu_device->SetPipeline(m_downsample_blur_pipeline.get());
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
g_gpu_device->Draw(3, 0);
g_gpu_device->DrawWithPushConstants(3, 0, &uniforms, sizeof(uniforms));
weight_texture->MakeReadyForSampling();
}
@ -4266,8 +4258,7 @@ void GPU_HW::DownsampleFramebufferAdaptive(GPUTexture* source, u32 left, u32 top
g_gpu_device->SetTextureSampler(1, weight_texture.get(), m_downsample_lod_sampler.get());
g_gpu_device->SetViewportAndScissor(GSVector4i(0, 0, width, height));
g_gpu_device->SetPipeline(m_downsample_composite_pipeline.get());
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
g_gpu_device->Draw(3, 0);
g_gpu_device->DrawWithPushConstants(3, 0, &uniforms, sizeof(uniforms));
m_downsample_texture->MakeReadyForSampling();
}
@ -4300,8 +4291,7 @@ void GPU_HW::DownsampleFramebufferBoxFilter(GPUTexture* source, u32 left, u32 to
g_gpu_device->SetPipeline(m_downsample_pass_pipeline.get());
g_gpu_device->SetTextureSampler(0, source, g_gpu_device->GetNearestSampler());
g_gpu_device->SetViewportAndScissor(0, 0, ds_width, ds_height);
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
g_gpu_device->Draw(3, 0);
g_gpu_device->DrawWithPushConstants(3, 0, uniforms, sizeof(uniforms));
RestoreDeviceContext();

@ -3463,7 +3463,7 @@ void GPUTextureCache::PreloadReplacementTextures()
#define UPDATE_PROGRESS() \
if (last_update_time.GetTimeSeconds() >= UPDATE_INTERVAL) \
{ \
FullscreenUI::RenderLoadingScreen( \
FullscreenUI::RenderLoadingScreen( \
image_path, TRANSLATE_SV("GPU_HW", "Preloading replacement textures..."), \
TinyString::from_format(TRANSLATE_FS("GPU_HW", "{0} of {1} textures"), num_textures_loaded, total_textures), 0, \
static_cast<int>(total_textures), static_cast<int>(num_textures_loaded)); \
@ -3837,9 +3837,8 @@ void GPUTextureCache::ApplyTextureReplacements(SourceKey key, HashType tex_hash,
GSVector2::store<true>(&uniforms[6], GSVector2::cxpr(1.0f) / texture_size);
g_gpu_device->SetViewportAndScissor(0, 0, new_width, new_height);
g_gpu_device->SetPipeline(s_state.replacement_upscale_pipeline.get());
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
g_gpu_device->SetTextureSampler(0, entry->texture.get(), g_gpu_device->GetNearestSampler());
g_gpu_device->Draw(3, 0);
g_gpu_device->DrawWithPushConstants(3, 0, uniforms, sizeof(uniforms));
for (const TextureReplacementSubImage& si : subimages)
{
@ -3860,8 +3859,7 @@ void GPUTextureCache::ApplyTextureReplacements(SourceKey key, HashType tex_hash,
g_gpu_device->GetNearestSampler());
g_gpu_device->SetPipeline(si.invert_alpha ? s_state.replacement_semitransparent_draw_pipeline.get() :
s_state.replacement_draw_pipeline.get());
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
g_gpu_device->Draw(3, 0);
g_gpu_device->DrawWithPushConstants(3, 0, uniforms, sizeof(uniforms));
}
g_gpu_device->CopyTextureRegion(replacement_tex.get(), 0, 0, 0, 0, s_state.replacement_texture_render_target.get(), 0,

@ -554,12 +554,12 @@ GPUDevice::PresentResult GPUPresenter::RenderDisplay(GPUTexture* target, const G
g_gpu_device->SetPipeline(m_border_overlay_pipeline.get());
g_gpu_device->SetTextureSampler(0, m_border_overlay_texture.get(), g_gpu_device->GetLinearSampler());
DrawScreenQuad(overlay_rect, GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f), target_size, final_target_size,
DisplayRotation::Normal, prerotation);
DisplayRotation::Normal, prerotation, nullptr, 0);
g_gpu_device->SetPipeline(m_present_copy_blend_pipeline.get());
g_gpu_device->SetTextureSampler(0, postfx_output, g_gpu_device->GetNearestSampler());
DrawScreenQuad(overlay_display_rect, src_uv_rect, target_size, final_target_size, DisplayRotation::Normal,
prerotation);
prerotation, nullptr, 0);
}
else
{
@ -568,7 +568,7 @@ GPUDevice::PresentResult GPUPresenter::RenderDisplay(GPUTexture* target, const G
g_gpu_device->SetPipeline(m_present_copy_pipeline.get());
g_gpu_device->SetTextureSampler(0, postfx_output, g_gpu_device->GetNearestSampler());
DrawScreenQuad(GSVector4i::loadh(postfx_size), src_uv_rect, target_size, final_target_size,
DisplayRotation::Normal, prerotation);
DisplayRotation::Normal, prerotation, nullptr, 0);
}
// All done
@ -594,7 +594,7 @@ GPUDevice::PresentResult GPUPresenter::RenderDisplay(GPUTexture* target, const G
g_gpu_device->SetTextureSampler(0, m_border_overlay_texture.get(), g_gpu_device->GetLinearSampler());
DrawScreenQuad(overlay_rect, GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f), target_size, final_target_size,
DisplayRotation::Normal, prerotation);
DisplayRotation::Normal, prerotation, nullptr, 0);
if (!overlay_display_rect.eq(draw_rect))
{
@ -762,13 +762,14 @@ void GPUPresenter::DrawDisplay(const GSVector2i target_size, const GSVector2i fi
GSVector4::store<true>(uniforms.src_size,
GSVector4::xyxy(display_texture_size, GSVector2::cxpr(1.0f) / display_texture_size));
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
DrawScreenQuad(display_rect, uv_rect, target_size, final_target_size, rotation, prerotation);
DrawScreenQuad(display_rect, uv_rect, target_size, final_target_size, rotation, prerotation, &uniforms,
sizeof(uniforms));
}
void GPUPresenter::DrawScreenQuad(const GSVector4i rect, const GSVector4 uv_rect, const GSVector2i target_size,
const GSVector2i final_target_size, DisplayRotation rotation,
WindowInfo::PreRotation prerotation)
WindowInfo::PreRotation prerotation, const void* push_constants,
u32 push_constants_size)
{
const GSVector4i real_rect = GPUSwapChain::PreRotateClipRect(prerotation, target_size, rect);
g_gpu_device->SetScissor(
@ -818,7 +819,10 @@ void GPUPresenter::DrawScreenQuad(const GSVector4i rect, const GSVector4 uv_rect
}
g_gpu_device->UnmapVertexBuffer(sizeof(GPUBackend::ScreenVertex), 4);
g_gpu_device->Draw(4, base_vertex);
if (push_constants_size > 0)
g_gpu_device->DrawWithPushConstants(4, base_vertex, push_constants, push_constants_size);
else
g_gpu_device->Draw(4, base_vertex);
}
GPUDevice::PresentResult GPUPresenter::ApplyDisplayPostProcess(GPUTexture* target, GPUTexture* input,
@ -922,10 +926,10 @@ bool GPUPresenter::Deinterlace(u32 field)
g_gpu_device->SetRenderTarget(m_deinterlace_texture.get());
g_gpu_device->SetPipeline(m_deinterlace_pipeline.get());
g_gpu_device->SetTextureSampler(0, src, g_gpu_device->GetNearestSampler());
const u32 uniforms[4] = {x, y, field, 0};
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
g_gpu_device->SetViewportAndScissor(0, 0, width, full_height);
g_gpu_device->Draw(3, 0);
const u32 uniforms[4] = {x, y, field, 0};
g_gpu_device->DrawWithPushConstants(3, 0, uniforms, sizeof(uniforms));
m_deinterlace_texture->MakeReadyForSampling();
SetDisplayTexture(m_deinterlace_texture.get(), 0, 0, width, full_height);
@ -987,10 +991,10 @@ bool GPUPresenter::Deinterlace(u32 field)
g_gpu_device->GetNearestSampler());
g_gpu_device->SetTextureSampler(3, m_deinterlace_buffers[(this_buffer - 3) % DEINTERLACE_BUFFER_COUNT].get(),
g_gpu_device->GetNearestSampler());
const u32 uniforms[] = {field, full_height};
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
g_gpu_device->SetViewportAndScissor(0, 0, width, full_height);
g_gpu_device->Draw(3, 0);
const u32 uniforms[] = {field, full_height};
g_gpu_device->DrawWithPushConstants(3, 0, uniforms, sizeof(uniforms));
m_deinterlace_texture->MakeReadyForSampling();
SetDisplayTexture(m_deinterlace_texture.get(), 0, 0, width, full_height);
@ -1036,10 +1040,10 @@ bool GPUPresenter::ApplyChromaSmoothing()
g_gpu_device->SetRenderTarget(m_chroma_smoothing_texture.get());
g_gpu_device->SetPipeline(m_chroma_smoothing_pipeline.get());
g_gpu_device->SetTextureSampler(0, m_display_texture, g_gpu_device->GetNearestSampler());
const u32 uniforms[] = {x, y, width - 1, height - 1};
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
g_gpu_device->SetViewportAndScissor(0, 0, width, height);
g_gpu_device->Draw(3, 0);
const u32 uniforms[] = {x, y, width - 1, height - 1};
g_gpu_device->DrawWithPushConstants(3, 0, uniforms, sizeof(uniforms));
m_chroma_smoothing_texture->MakeReadyForSampling();
SetDisplayTexture(m_chroma_smoothing_texture.get(), 0, 0, width, height);

@ -93,7 +93,7 @@ public:
// Draws the specified bounding box with display rotation and pre-rotation.
static void DrawScreenQuad(const GSVector4i rect, const GSVector4 uv_rect, const GSVector2i target_size,
const GSVector2i final_target_size, DisplayRotation uv_rotation,
WindowInfo::PreRotation prerotation);
WindowInfo::PreRotation prerotation, const void* push_constants, u32 push_constants_size);
private:
enum : u32

@ -1169,6 +1169,13 @@ void D3D11Device::Draw(u32 vertex_count, u32 base_vertex)
m_context->Draw(vertex_count, base_vertex);
}
void D3D11Device::DrawWithPushConstants(u32 vertex_count, u32 base_vertex, const void* push_constants,
u32 push_constants_size)
{
PushUniformBuffer(push_constants, push_constants_size);
Draw(vertex_count, base_vertex);
}
void D3D11Device::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
{
DebugAssert(!m_vertex_buffer.IsMapped() && !m_index_buffer.IsMapped() && !m_current_compute_shader);
@ -1176,9 +1183,11 @@ void D3D11Device::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
m_context->DrawIndexed(index_count, base_index, base_vertex);
}
void D3D11Device::DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type)
void D3D11Device::DrawIndexedWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex,
const void* push_constants, u32 push_constants_size)
{
Panic("Barriers are not supported");
PushUniformBuffer(push_constants, push_constants_size);
DrawIndexed(index_count, base_index, base_vertex);
}
void D3D11Device::Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
@ -1192,3 +1201,11 @@ void D3D11Device::Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 grou
const u32 groups_z = threads_z / group_size_z;
m_context->Dispatch(groups_x, groups_y, groups_z);
}
void D3D11Device::DispatchWithPushConstants(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x,
u32 group_size_y, u32 group_size_z, const void* push_constants,
u32 push_constants_size)
{
PushUniformBuffer(push_constants, push_constants_size);
Dispatch(threads_x, threads_y, threads_z, group_size_x, group_size_y, group_size_z);
}

@ -89,7 +89,6 @@ public:
void UnmapVertexBuffer(u32 vertex_size, u32 vertex_count) override;
void MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index) override;
void UnmapIndexBuffer(u32 used_index_count) override;
void PushUniformBuffer(const void* data, u32 data_size) override;
void* MapUniformBuffer(u32 size) override;
void UnmapUniformBuffer(u32 size) override;
void SetRenderTargets(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds,
@ -100,10 +99,15 @@ public:
void SetViewport(const GSVector4i rc) override;
void SetScissor(const GSVector4i rc) override;
void Draw(u32 vertex_count, u32 base_vertex) override;
void DrawWithPushConstants(u32 vertex_count, u32 base_vertex, const void* push_constants,
u32 push_constants_size) override;
void DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex) override;
void DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type) override;
void DrawIndexedWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex, const void* push_constants,
u32 push_constants_size) override;
void Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
u32 group_size_z) override;
void DispatchWithPushConstants(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
u32 group_size_z, const void* push_constants, u32 push_constants_size) override;
bool SetGPUTimingEnabled(bool enabled) override;
float GetAndResetAccumulatedGPUTime() override;
@ -147,6 +151,7 @@ private:
bool CreateBuffers(Error* error);
void DestroyBuffers();
void BindUniformBuffer(u32 offset, u32 size);
void PushUniformBuffer(const void* data, u32 data_size);
void UnbindComputePipeline();
bool IsRenderTargetBound(const D3D11Texture* tex) const;

@ -1600,7 +1600,8 @@ void D3D12Device::UnmapIndexBuffer(u32 used_index_count)
m_index_buffer.CommitMemory(upload_size);
}
void D3D12Device::PushUniformBuffer(const void* data, u32 data_size)
void D3D12Device::PushUniformBuffer(ID3D12GraphicsCommandList4* const cmdlist, bool compute, const void* data,
u32 data_size)
{
static constexpr std::array<u8, static_cast<u8>(GPUPipeline::Layout::MaxCount)> push_parameters = {
0, // SingleTextureAndUBO
@ -1611,19 +1612,11 @@ void D3D12Device::PushUniformBuffer(const void* data, u32 data_size)
2, // ComputeSingleTextureAndPushConstants
};
DebugAssert(data_size < UNIFORM_PUSH_CONSTANTS_SIZE);
if (m_dirty_flags & DIRTY_FLAG_PIPELINE_LAYOUT)
{
m_dirty_flags &= ~DIRTY_FLAG_PIPELINE_LAYOUT;
UpdateRootSignature();
}
s_stats.buffer_streamed += data_size;
const u32 push_param =
push_parameters[static_cast<u8>(m_current_pipeline_layout)] + BoolToUInt8(IsUsingROVRootSignature());
ID3D12GraphicsCommandList4* cmdlist = GetCommandList();
if (!IsUsingComputeRootSignature())
if (!compute)
cmdlist->SetGraphicsRoot32BitConstants(push_param, data_size / 4u, data, 0);
else
cmdlist->SetComputeRoot32BitConstants(push_param, data_size / 4u, data, 0);
@ -2633,6 +2626,17 @@ void D3D12Device::Draw(u32 vertex_count, u32 base_vertex)
GetCommandList()->DrawInstanced(vertex_count, 1, base_vertex, 0);
}
void D3D12Device::DrawWithPushConstants(u32 vertex_count, u32 base_vertex, const void* push_constants,
u32 push_constants_size)
{
PreDrawCheck();
s_stats.num_draws++;
ID3D12GraphicsCommandList4* const cmdlist = GetCommandList();
PushUniformBuffer(cmdlist, false, push_constants, push_constants_size);
cmdlist->DrawInstanced(vertex_count, 1, base_vertex, 0);
}
void D3D12Device::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
{
PreDrawCheck();
@ -2640,9 +2644,15 @@ void D3D12Device::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
GetCommandList()->DrawIndexedInstanced(index_count, 1, base_index, base_vertex, 0);
}
void D3D12Device::DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type)
void D3D12Device::DrawIndexedWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex,
const void* push_constants, u32 push_constants_size)
{
Panic("Barriers are not supported");
PreDrawCheck();
s_stats.num_draws++;
ID3D12GraphicsCommandList4* const cmdlist = GetCommandList();
PushUniformBuffer(cmdlist, false, push_constants, push_constants_size);
cmdlist->DrawIndexedInstanced(index_count, 1, base_index, base_vertex, 0);
}
void D3D12Device::Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
@ -2656,3 +2666,19 @@ void D3D12Device::Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 grou
const u32 groups_z = threads_z / group_size_z;
GetCommandList()->Dispatch(groups_x, groups_y, groups_z);
}
void D3D12Device::DispatchWithPushConstants(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x,
u32 group_size_y, u32 group_size_z, const void* push_constants,
u32 push_constants_size)
{
PreDispatchCheck();
s_stats.num_draws++;
ID3D12GraphicsCommandList4* const cmdlist = GetCommandList();
PushUniformBuffer(cmdlist, true, push_constants, push_constants_size);
const u32 groups_x = threads_x / group_size_x;
const u32 groups_y = threads_y / group_size_y;
const u32 groups_z = threads_z / group_size_z;
cmdlist->Dispatch(groups_x, groups_y, groups_z);
}

@ -112,7 +112,6 @@ public:
void UnmapVertexBuffer(u32 vertex_size, u32 vertex_count) override;
void MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index) override;
void UnmapIndexBuffer(u32 used_index_count) override;
void PushUniformBuffer(const void* data, u32 data_size) override;
void* MapUniformBuffer(u32 size) override;
void UnmapUniformBuffer(u32 size) override;
void SetRenderTargets(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds,
@ -123,10 +122,15 @@ public:
void SetViewport(const GSVector4i rc) override;
void SetScissor(const GSVector4i rc) override;
void Draw(u32 vertex_count, u32 base_vertex) override;
void DrawWithPushConstants(u32 vertex_count, u32 base_vertex, const void* push_constants,
u32 push_constants_size) override;
void DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex) override;
void DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type) override;
void DrawIndexedWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex, const void* push_constants,
u32 push_constants_size) override;
void Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
u32 group_size_z) override;
void DispatchWithPushConstants(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
u32 group_size_z, const void* push_constants, u32 push_constants_size) override;
bool SetGPUTimingEnabled(bool enabled) override;
float GetAndResetAccumulatedGPUTime() override;
@ -281,10 +285,10 @@ private:
void SetScissor(ID3D12GraphicsCommandList4* cmdlist);
/// Applies any changed state.
ID3D12RootSignature* GetCurrentRootSignature() const;
void SetInitialPipelineState();
void PreDrawCheck();
void PreDispatchCheck();
void PushUniformBuffer(ID3D12GraphicsCommandList4* const cmdlist, bool compute, const void* data, u32 data_size);
bool IsUsingROVRootSignature() const;
bool IsUsingComputeRootSignature() const;

@ -771,6 +771,18 @@ void GPUDevice::SetViewportAndScissor(const GSVector4i rc)
SetScissor(rc);
}
void GPUDevice::DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type)
{
Panic("Barrier draws are not supported on this API.");
}
void GPUDevice::DrawIndexedWithBarrierWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex,
const void* push_constants, u32 push_constants_size,
DrawBarrier type)
{
Panic("Barrier draws are not supported on this API.");
}
void GPUDevice::ClearRenderTarget(GPUTexture* t, u32 c)
{
t->SetClearColor(c);

@ -874,7 +874,6 @@ public:
void UploadIndexBuffer(const DrawIndex* indices, u32 index_count, u32* base_index);
/// Uniform buffer abstraction.
virtual void PushUniformBuffer(const void* data, u32 data_size) = 0;
virtual void* MapUniformBuffer(u32 size) = 0;
virtual void UnmapUniformBuffer(u32 size) = 0;
void UploadUniformBuffer(const void* data, u32 data_size);
@ -896,10 +895,20 @@ public:
// Drawing abstraction.
virtual void Draw(u32 vertex_count, u32 base_vertex) = 0;
virtual void DrawWithPushConstants(u32 vertex_count, u32 base_vertex, const void* push_constants,
u32 push_constants_size) = 0;
virtual void DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex) = 0;
virtual void DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type) = 0;
virtual void DrawIndexedWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex,
const void* push_constants, u32 push_constants_size) = 0;
virtual void DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type);
virtual void DrawIndexedWithBarrierWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex,
const void* push_constants, u32 push_constants_size,
DrawBarrier type);
virtual void Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
u32 group_size_z) = 0;
virtual void DispatchWithPushConstants(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x,
u32 group_size_y, u32 group_size_z, const void* push_constants,
u32 push_constants_size) = 0;
/// Returns false if the window was completely occluded.
virtual PresentResult BeginPresent(GPUSwapChain* swap_chain, u32 clear_color = DEFAULT_CLEAR_COLOR) = 0;

@ -288,7 +288,6 @@ public:
void UnmapVertexBuffer(u32 vertex_size, u32 vertex_count) override;
void MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index) override;
void UnmapIndexBuffer(u32 used_index_count) override;
void PushUniformBuffer(const void* data, u32 data_size) override;
void* MapUniformBuffer(u32 size) override;
void UnmapUniformBuffer(u32 size) override;
void SetRenderTargets(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds,
@ -299,10 +298,19 @@ public:
void SetViewport(const GSVector4i rc) override;
void SetScissor(const GSVector4i rc) override;
void Draw(u32 vertex_count, u32 base_vertex) override;
void DrawWithPushConstants(u32 vertex_count, u32 base_vertex, const void* push_constants,
u32 push_constants_size) override;
void DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex) override;
void DrawIndexedWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex, const void* push_constants,
u32 push_constants_size) override;
void DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type) override;
void DrawIndexedWithBarrierWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex,
const void* push_constants, u32 push_constants_size,
DrawBarrier type) override;
void Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
u32 group_size_z) override;
void DispatchWithPushConstants(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
u32 group_size_z, const void* push_constants, u32 push_constants_size) override;
bool SetGPUTimingEnabled(bool enabled) override;
float GetAndResetAccumulatedGPUTime() override;
@ -385,6 +393,8 @@ private:
void PreDrawCheck();
void SetInitialEncoderState();
void PushUniformBuffer(const void* data, u32 data_size);
void SubmitDrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type);
void SetViewportInRenderEncoder();
void SetScissorInRenderEncoder();
void CommitRenderTargetClears();

@ -284,9 +284,8 @@ void MetalDevice::RenderBlankFrame(MetalSwapChain* swap_chain)
}
}
bool MetalDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags,
const WindowInfo& wi, GPUVSyncMode vsync_mode,
bool allow_present_throttle,
bool MetalDevice::CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi,
GPUVSyncMode vsync_mode, bool allow_present_throttle,
const ExclusiveFullscreenMode* exclusive_fullscreen_mode,
std::optional<bool> exclusive_fullscreen_control, Error* error)
{
@ -2299,6 +2298,15 @@ void MetalDevice::Draw(u32 vertex_count, u32 base_vertex)
[m_render_encoder drawPrimitives:m_current_pipeline->GetPrimitive() vertexStart:base_vertex vertexCount:vertex_count];
}
void MetalDevice::DrawWithPushConstants(u32 vertex_count, u32 base_vertex, const void* push_constants,
u32 push_constants_size)
{
PreDrawCheck();
PushUniformBuffer(push_constants, push_constants_size);
s_stats.num_draws++;
[m_render_encoder drawPrimitives:m_current_pipeline->GetPrimitive() vertexStart:base_vertex vertexCount:vertex_count];
}
void MetalDevice::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
{
PreDrawCheck();
@ -2316,16 +2324,51 @@ void MetalDevice::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
baseInstance:0];
}
void MetalDevice::DrawIndexedWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex,
const void* push_constants, u32 push_constants_size)
{
PreDrawCheck();
PushUniformBuffer(push_constants, push_constants_size);
s_stats.num_draws++;
const u32 index_offset = base_index * sizeof(u16);
[m_render_encoder drawIndexedPrimitives:m_current_pipeline->GetPrimitive()
indexCount:index_count
indexType:MTLIndexTypeUInt16
indexBuffer:m_index_buffer.GetBuffer()
indexBufferOffset:index_offset
instanceCount:1
baseVertex:base_vertex
baseInstance:0];
}
void MetalDevice::DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type)
{
// Shouldn't be using this with framebuffer fetch.
DebugAssert(!m_features.framebuffer_fetch);
PreDrawCheck();
SubmitDrawIndexedWithBarrier(index_count, base_index, base_vertex, type);
}
const bool skip_first_barrier = !InRenderPass();
void MetalDevice::DrawIndexedWithBarrierWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex,
const void* push_constants, u32 push_constants_size,
DrawBarrier type)
{
PreDrawCheck();
// TODO: The first barrier is unnecessary if we're starting the render pass.
PushUniformBuffer(push_constants, push_constants_size);
SubmitDrawIndexedWithBarrier(index_count, base_index, base_vertex, type);
}
void MetalDevice::SubmitDrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type)
{
// Shouldn't be using this with framebuffer fetch.
DebugAssert(!m_features.framebuffer_fetch);
const MTLPrimitiveType primitive = m_current_pipeline->GetPrimitive();
const id<MTLBuffer> index_buffer = m_index_buffer.GetBuffer();
u32 index_offset = base_index * sizeof(u16);
switch (type)
@ -2334,10 +2377,10 @@ void MetalDevice::DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 ba
{
s_stats.num_draws++;
[m_render_encoder drawIndexedPrimitives:m_current_pipeline->GetPrimitive()
[m_render_encoder drawIndexedPrimitives:primitive
indexCount:index_count
indexType:MTLIndexTypeUInt16
indexBuffer:m_index_buffer.GetBuffer()
indexBuffer:index_buffer
indexBufferOffset:index_offset
instanceCount:1
baseVertex:base_vertex
@ -2350,18 +2393,15 @@ void MetalDevice::DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 ba
DebugAssert(m_num_current_render_targets == 1);
s_stats.num_draws++;
if (!skip_first_barrier)
{
s_stats.num_barriers++;
[m_render_encoder memoryBarrierWithScope:MTLBarrierScopeRenderTargets
afterStages:MTLRenderStageFragment
beforeStages:MTLRenderStageFragment];
}
s_stats.num_barriers++;
[m_render_encoder memoryBarrierWithScope:MTLBarrierScopeRenderTargets
afterStages:MTLRenderStageFragment
beforeStages:MTLRenderStageFragment];
[m_render_encoder drawIndexedPrimitives:m_current_pipeline->GetPrimitive()
[m_render_encoder drawIndexedPrimitives:primitive
indexCount:index_count
indexType:MTLIndexTypeUInt16
indexBuffer:m_index_buffer.GetBuffer()
indexBuffer:index_buffer
indexBufferOffset:index_offset
instanceCount:1
baseVertex:base_vertex
@ -2381,33 +2421,9 @@ void MetalDevice::DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 ba
{3, 1}, // MTLPrimitiveTypeTriangleStrip
};
const u32 first_step =
vertices_per_primitive[static_cast<size_t>(m_current_pipeline->GetPrimitive())][0] * sizeof(u16);
const u32 index_step =
vertices_per_primitive[static_cast<size_t>(m_current_pipeline->GetPrimitive())][1] * sizeof(u16);
const u32 first_step = vertices_per_primitive[static_cast<size_t>(primitive)][0] * sizeof(u16);
const u32 index_step = vertices_per_primitive[static_cast<size_t>(primitive)][1] * sizeof(u16);
const u32 end_offset = (base_index + index_count) * sizeof(u16);
// first primitive
if (!skip_first_barrier)
{
s_stats.num_barriers++;
[m_render_encoder memoryBarrierWithScope:MTLBarrierScopeRenderTargets
afterStages:MTLRenderStageFragment
beforeStages:MTLRenderStageFragment];
}
s_stats.num_draws++;
[m_render_encoder drawIndexedPrimitives:m_current_pipeline->GetPrimitive()
indexCount:index_count
indexType:MTLIndexTypeUInt16
indexBuffer:m_index_buffer.GetBuffer()
indexBufferOffset:index_offset
instanceCount:1
baseVertex:base_vertex
baseInstance:0];
index_offset += first_step;
// remaining primitices
for (; index_offset < end_offset; index_offset += index_step)
{
s_stats.num_barriers++;
@ -2416,10 +2432,10 @@ void MetalDevice::DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 ba
[m_render_encoder memoryBarrierWithScope:MTLBarrierScopeRenderTargets
afterStages:MTLRenderStageFragment
beforeStages:MTLRenderStageFragment];
[m_render_encoder drawIndexedPrimitives:m_current_pipeline->GetPrimitive()
[m_render_encoder drawIndexedPrimitives:primitive
indexCount:index_count
indexType:MTLIndexTypeUInt16
indexBuffer:m_index_buffer.GetBuffer()
indexBuffer:index_buffer
indexBufferOffset:index_offset
instanceCount:1
baseVertex:base_vertex
@ -2450,6 +2466,26 @@ void MetalDevice::Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 grou
threadsPerThreadgroup:MTLSizeMake(group_size_x, group_size_y, group_size_z)];
}
void MetalDevice::DispatchWithPushConstants(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x,
u32 group_size_y, u32 group_size_z, const void* push_constants,
u32 push_constants_size)
{
if (!InComputePass())
{
if (InRenderPass())
EndRenderPass();
BeginComputePass();
}
DebugAssert(m_current_pipeline && m_current_pipeline->IsComputePipeline());
PushUniformBuffer(push_constants, push_constants_size);
// TODO: We could remap to the optimal group size..
[m_compute_encoder dispatchThreads:MTLSizeMake(threads_x, threads_y, threads_z)
threadsPerThreadgroup:MTLSizeMake(group_size_x, group_size_y, group_size_z)];
}
id<MTLBlitCommandEncoder> MetalDevice::GetBlitEncoder(bool is_inline)
{
@autoreleasepool

@ -1032,6 +1032,13 @@ void OpenGLDevice::Draw(u32 vertex_count, u32 base_vertex)
glDrawArrays(m_current_pipeline->GetTopology(), 0, vertex_count);
}
void OpenGLDevice::DrawWithPushConstants(u32 vertex_count, u32 base_vertex, const void* push_constants,
u32 push_constants_size)
{
PushUniformBuffer(push_constants, push_constants_size);
Draw(vertex_count, base_vertex);
}
void OpenGLDevice::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
{
s_stats.num_draws++;
@ -1049,9 +1056,11 @@ void OpenGLDevice::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
glDrawElements(m_current_pipeline->GetTopology(), index_count, GL_UNSIGNED_SHORT, indices);
}
void OpenGLDevice::DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type)
void OpenGLDevice::DrawIndexedWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex,
const void* push_constants, u32 push_constants_size)
{
Panic("Barriers are not supported");
PushUniformBuffer(push_constants, push_constants_size);
DrawIndexed(index_count, base_index, base_vertex);
}
void OpenGLDevice::Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
@ -1060,6 +1069,13 @@ void OpenGLDevice::Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 gro
Panic("Compute shaders are not supported");
}
void OpenGLDevice::DispatchWithPushConstants(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x,
u32 group_size_y, u32 group_size_z, const void* push_constants,
u32 push_constants_size)
{
Panic("Compute shaders are not supported");
}
void OpenGLDevice::MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map_ptr, u32* map_space,
u32* map_base_vertex)
{

@ -95,7 +95,6 @@ public:
void UnmapVertexBuffer(u32 vertex_size, u32 vertex_count) override;
void MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index) override;
void UnmapIndexBuffer(u32 used_index_count) override;
void PushUniformBuffer(const void* data, u32 data_size) override;
void* MapUniformBuffer(u32 size) override;
void UnmapUniformBuffer(u32 size) override;
void SetRenderTargets(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds,
@ -106,10 +105,15 @@ public:
void SetViewport(const GSVector4i rc) override;
void SetScissor(const GSVector4i rc) override;
void Draw(u32 vertex_count, u32 base_vertex) override;
void DrawWithPushConstants(u32 vertex_count, u32 base_vertex, const void* push_constants,
u32 push_constants_size) override;
void DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex) override;
void DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type) override;
void DrawIndexedWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex, const void* push_constants,
u32 push_constants_size) override;
void Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
u32 group_size_z) override;
void DispatchWithPushConstants(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
u32 group_size_z, const void* push_constants, u32 push_constants_size) override;
PresentResult BeginPresent(GPUSwapChain* swap_chain, u32 clear_color) override;
void EndPresent(GPUSwapChain* swap_chain, bool explicit_present, u64 present_time) override;
@ -171,6 +175,7 @@ private:
static GLuint CreateFramebuffer(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds, u32 flags);
static void DestroyFramebuffer(GLuint fbo);
void PushUniformBuffer(const void* data, u32 data_size);
void UpdateViewport();
void UpdateScissor();

@ -2860,12 +2860,13 @@ void VulkanDevice::UnmapIndexBuffer(u32 used_index_count)
m_index_buffer.CommitMemory(size);
}
void VulkanDevice::PushUniformBuffer(const void* data, u32 data_size)
void VulkanDevice::PushUniformBuffer(bool is_compute, const void* data, u32 data_size)
{
DebugAssert(data_size < UNIFORM_PUSH_CONSTANTS_SIZE);
s_stats.buffer_streamed += data_size;
vkCmdPushConstants(m_current_command_buffer, GetCurrentVkPipelineLayout(), UNIFORM_PUSH_CONSTANTS_STAGES, 0,
data_size, data);
vkCmdPushConstants(m_current_command_buffer, GetCurrentVkPipelineLayout(is_compute),
is_compute ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT : UNIFORM_PUSH_CONSTANTS_STAGES, 0, data_size,
data);
}
void* VulkanDevice::MapUniformBuffer(u32 size)
@ -3667,11 +3668,9 @@ VulkanDevice::PipelineLayoutType VulkanDevice::GetPipelineLayoutType(GPUPipeline
PipelineLayoutType::Normal);
}
VkPipelineLayout VulkanDevice::GetCurrentVkPipelineLayout() const
VkPipelineLayout VulkanDevice::GetCurrentVkPipelineLayout(bool is_compute) const
{
return m_pipeline_layouts[IsComputeLayout(m_current_pipeline_layout) ?
0 :
static_cast<size_t>(GetPipelineLayoutType(m_current_render_pass_flags))]
return m_pipeline_layouts[is_compute ? 0 : static_cast<size_t>(GetPipelineLayoutType(m_current_render_pass_flags))]
[static_cast<size_t>(m_current_pipeline_layout)];
}
@ -3885,9 +3884,10 @@ bool VulkanDevice::UpdateDescriptorSetsForLayout(u32 dirty)
{
[[maybe_unused]] bool new_dynamic_offsets = false;
constexpr bool is_compute = IsComputeLayout(layout);
constexpr VkPipelineBindPoint vk_bind_point =
(IsComputeLayout(layout) ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS);
const VkPipelineLayout vk_pipeline_layout = GetCurrentVkPipelineLayout();
(is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS);
const VkPipelineLayout vk_pipeline_layout = GetCurrentVkPipelineLayout(is_compute);
std::array<VkDescriptorSet, 3> ds;
u32 first_ds = 0;
u32 num_ds = 0;
@ -4053,6 +4053,16 @@ void VulkanDevice::Draw(u32 vertex_count, u32 base_vertex)
vkCmdDraw(m_current_command_buffer, vertex_count, 1, base_vertex, 0);
}
void VulkanDevice::DrawWithPushConstants(u32 vertex_count, u32 base_vertex, const void* push_constants,
u32 push_constants_size)
{
PreDrawCheck();
s_stats.num_draws++;
PushUniformBuffer(false, push_constants, push_constants_size);
vkCmdDraw(m_current_command_buffer, vertex_count, 1, base_vertex, 0);
}
void VulkanDevice::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
{
PreDrawCheck();
@ -4060,6 +4070,15 @@ void VulkanDevice::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
vkCmdDrawIndexed(m_current_command_buffer, index_count, 1, base_index, base_vertex, 0);
}
void VulkanDevice::DrawIndexedWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex,
const void* push_constants, u32 push_constants_size)
{
PreDrawCheck();
s_stats.num_draws++;
PushUniformBuffer(false, push_constants, push_constants_size);
vkCmdDrawIndexed(m_current_command_buffer, index_count, 1, base_index, base_vertex, 0);
}
VkImageMemoryBarrier VulkanDevice::GetColorBufferBarrier(const VulkanTexture* rt) const
{
const VkImageLayout vk_layout = m_optional_extensions.vk_khr_dynamic_rendering_local_read ?
@ -4082,9 +4101,20 @@ VkImageMemoryBarrier VulkanDevice::GetColorBufferBarrier(const VulkanTexture* rt
void VulkanDevice::DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type)
{
PreDrawCheck();
SubmitDrawIndexedWithBarrier(index_count, base_index, base_vertex, type);
}
// TODO: The first barrier is unnecessary if we're starting the render pass.
void VulkanDevice::DrawIndexedWithBarrierWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex,
const void* push_constants, u32 push_constants_size,
DrawBarrier type)
{
PreDrawCheck();
PushUniformBuffer(false, push_constants, push_constants_size);
SubmitDrawIndexedWithBarrier(index_count, base_index, base_vertex, type);
}
void VulkanDevice::SubmitDrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type)
{
switch (type)
{
case GPUDevice::DrawBarrier::None:
@ -4146,3 +4176,18 @@ void VulkanDevice::Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 gro
const u32 groups_z = threads_z / group_size_z;
vkCmdDispatch(m_current_command_buffer, groups_x, groups_y, groups_z);
}
void VulkanDevice::DispatchWithPushConstants(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x,
u32 group_size_y, u32 group_size_z, const void* push_constants,
u32 push_constants_size)
{
PreDispatchCheck();
s_stats.num_draws++;
PushUniformBuffer(true, push_constants, push_constants_size);
const u32 groups_x = threads_x / group_size_x;
const u32 groups_y = threads_y / group_size_y;
const u32 groups_z = threads_z / group_size_z;
vkCmdDispatch(m_current_command_buffer, groups_x, groups_y, groups_z);
}

@ -126,7 +126,6 @@ public:
void UnmapVertexBuffer(u32 vertex_size, u32 vertex_count) override;
void MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index) override;
void UnmapIndexBuffer(u32 used_index_count) override;
void PushUniformBuffer(const void* data, u32 data_size) override;
void* MapUniformBuffer(u32 size) override;
void UnmapUniformBuffer(u32 size) override;
void SetRenderTargets(GPUTexture* const* rts, u32 num_rts, GPUTexture* ds,
@ -137,10 +136,19 @@ public:
void SetViewport(const GSVector4i rc) override;
void SetScissor(const GSVector4i rc) override;
void Draw(u32 vertex_count, u32 base_vertex) override;
void DrawWithPushConstants(u32 vertex_count, u32 base_vertex, const void* push_constants,
u32 push_constants_size) override;
void DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex) override;
void DrawIndexedWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex, const void* push_constants,
u32 push_constants_size) override;
void DrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type) override;
void DrawIndexedWithBarrierWithPushConstants(u32 index_count, u32 base_index, u32 base_vertex,
const void* push_constants, u32 push_constants_size,
DrawBarrier type) override;
void Dispatch(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
u32 group_size_z) override;
void DispatchWithPushConstants(u32 threads_x, u32 threads_y, u32 threads_z, u32 group_size_x, u32 group_size_y,
u32 group_size_z, const void* push_constants, u32 push_constants_size) override;
bool SetGPUTimingEnabled(bool enabled) override;
float GetAndResetAccumulatedGPUTime() override;
@ -367,10 +375,12 @@ private:
/// Applies any changed state.
static PipelineLayoutType GetPipelineLayoutType(GPUPipeline::RenderPassFlag flags);
VkPipelineLayout GetCurrentVkPipelineLayout() const;
VkPipelineLayout GetCurrentVkPipelineLayout(bool is_compute) const;
void SetInitialPipelineState();
void PreDrawCheck();
void PreDispatchCheck();
void PushUniformBuffer(bool is_compute, const void* data, u32 data_size);
void SubmitDrawIndexedWithBarrier(u32 index_count, u32 base_index, u32 base_vertex, DrawBarrier type);
template<GPUPipeline::Layout layout>
bool UpdateDescriptorSetsForLayout(u32 dirty);

Loading…
Cancel
Save