mirror of https://git.suyu.dev/suyu/suyu
metal: don't bind resources that are already bound
This commit is contained in:
parent
4771cd1602
commit
98c4ff461f
|
@ -11,12 +11,12 @@ CommandRecorder::CommandRecorder(const Device& device_) : device(device_) {}
|
|||
CommandRecorder::~CommandRecorder() = default;
|
||||
|
||||
void CommandRecorder::BeginOrContinueRenderPass(MTL::RenderPassDescriptor* render_pass) {
|
||||
if (render_pass != bound_render_pass) {
|
||||
if (render_pass != render_state.render_pass) {
|
||||
RequireCommandBuffer();
|
||||
EndEncoding();
|
||||
encoder = command_buffer->renderCommandEncoder(render_pass);
|
||||
encoder_type = EncoderType::Render;
|
||||
bound_render_pass = render_pass;
|
||||
render_state.render_pass = render_pass;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,9 @@ void CommandRecorder::EndEncoding() {
|
|||
encoder->endEncoding();
|
||||
//[encoder release];
|
||||
encoder = nullptr;
|
||||
bound_render_pass = nullptr;
|
||||
if (encoder_type == EncoderType::Render) {
|
||||
render_state = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,27 @@ class Device;
|
|||
|
||||
enum class EncoderType { Render, Compute, Blit };
|
||||
|
||||
constexpr size_t MAX_BUFFERS = 31;
|
||||
constexpr size_t MAX_TEXTURES = 31;
|
||||
constexpr size_t MAX_SAMPLERS = 31;
|
||||
|
||||
struct RenderState {
|
||||
MTL::RenderPassDescriptor* render_pass{nullptr};
|
||||
MTL::RenderPipelineState* pipeline_state{nullptr};
|
||||
|
||||
MTL::Buffer* vertex_buffers[MAX_BUFFERS] = {nullptr};
|
||||
MTL::Buffer* fragment_buffers[MAX_BUFFERS] = {nullptr};
|
||||
MTL::Buffer* compute_buffers[MAX_BUFFERS] = {nullptr};
|
||||
|
||||
MTL::Texture* vertex_textures[MAX_TEXTURES] = {nullptr};
|
||||
MTL::Texture* fragment_textures[MAX_TEXTURES] = {nullptr};
|
||||
MTL::Texture* compute_textures[MAX_TEXTURES] = {nullptr};
|
||||
|
||||
MTL::SamplerState* vertex_sampler_states[MAX_SAMPLERS] = {nullptr};
|
||||
MTL::SamplerState* fragment_sampler_states[MAX_SAMPLERS] = {nullptr};
|
||||
MTL::SamplerState* compute_sampler_states[MAX_SAMPLERS] = {nullptr};
|
||||
};
|
||||
|
||||
// TODO: whenever a render pass gets interrupted by either a compute or blit command and application
|
||||
// then tries to perform a render command, begin the same render pass, but with all load actions set
|
||||
// to "load"
|
||||
|
@ -61,6 +82,77 @@ public:
|
|||
return static_cast<MTL::BlitCommandEncoder*>(encoder);
|
||||
}
|
||||
|
||||
// Render commands
|
||||
inline void SetRenderPipelineState(MTL::RenderPipelineState* pipeline_state) {
|
||||
if (pipeline_state != render_state.pipeline_state) {
|
||||
GetRenderCommandEncoder()->setRenderPipelineState(pipeline_state);
|
||||
render_state.pipeline_state = pipeline_state;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetVertexBuffer(MTL::Buffer* buffer, size_t index) {
|
||||
if (buffer != render_state.vertex_buffers[index]) {
|
||||
GetRenderCommandEncoder()->setVertexBuffer(buffer, index, 0);
|
||||
render_state.vertex_buffers[index] = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetFragmentBuffer(MTL::Buffer* buffer, size_t index) {
|
||||
if (buffer != render_state.fragment_buffers[index]) {
|
||||
GetRenderCommandEncoder()->setFragmentBuffer(buffer, index, 0);
|
||||
render_state.fragment_buffers[index] = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetComputeBuffer(MTL::Buffer* buffer, size_t index) {
|
||||
if (buffer != render_state.compute_buffers[index]) {
|
||||
GetComputeCommandEncoder()->setBuffer(buffer, index, 0);
|
||||
render_state.compute_buffers[index] = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetVertexTexture(MTL::Texture* texture, size_t index) {
|
||||
if (texture != render_state.vertex_textures[index]) {
|
||||
GetRenderCommandEncoder()->setVertexTexture(texture, index);
|
||||
render_state.vertex_textures[index] = texture;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetFragmentTexture(MTL::Texture* texture, size_t index) {
|
||||
if (texture != render_state.fragment_textures[index]) {
|
||||
GetRenderCommandEncoder()->setFragmentTexture(texture, index);
|
||||
render_state.fragment_textures[index] = texture;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetComputeTexture(MTL::Texture* texture, size_t index) {
|
||||
if (texture != render_state.compute_textures[index]) {
|
||||
GetComputeCommandEncoder()->setTexture(texture, index);
|
||||
render_state.compute_textures[index] = texture;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetVertexSamplerState(MTL::SamplerState* sampler_state, size_t index) {
|
||||
if (sampler_state != render_state.vertex_sampler_states[index]) {
|
||||
GetRenderCommandEncoder()->setVertexSamplerState(sampler_state, index);
|
||||
render_state.vertex_sampler_states[index] = sampler_state;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetFragmentSamplerState(MTL::SamplerState* sampler_state, size_t index) {
|
||||
if (sampler_state != render_state.fragment_sampler_states[index]) {
|
||||
GetRenderCommandEncoder()->setFragmentSamplerState(sampler_state, index);
|
||||
render_state.fragment_sampler_states[index] = sampler_state;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetComputeSamplerState(MTL::SamplerState* sampler_state, size_t index) {
|
||||
if (sampler_state != render_state.compute_sampler_states[index]) {
|
||||
GetComputeCommandEncoder()->setSamplerState(sampler_state, index);
|
||||
render_state.compute_sampler_states[index] = sampler_state;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const Device& device;
|
||||
|
||||
|
@ -71,8 +163,8 @@ private:
|
|||
|
||||
EncoderType encoder_type;
|
||||
|
||||
// Keep track of last bound render pass
|
||||
MTL::RenderPassDescriptor* bound_render_pass{nullptr};
|
||||
// Keep track of bound resources
|
||||
RenderState render_state{};
|
||||
|
||||
void RequireCommandBuffer();
|
||||
};
|
||||
|
|
|
@ -120,7 +120,7 @@ void GraphicsPipeline::Configure(bool is_indexed) {
|
|||
}
|
||||
command_recorder.BeginOrContinueRenderPass(framebuffer->GetHandle());
|
||||
|
||||
command_recorder.GetRenderCommandEncoder()->setRenderPipelineState(pipeline_state);
|
||||
command_recorder.SetRenderPipelineState(pipeline_state);
|
||||
|
||||
// Bind resources
|
||||
|
||||
|
@ -131,8 +131,8 @@ void GraphicsPipeline::Configure(bool is_indexed) {
|
|||
ImageView& image_view{texture_cache.GetImageView(views_it->id)};
|
||||
Sampler& sampler{texture_cache.GetSampler(*samplers_it)};
|
||||
|
||||
command_recorder.GetRenderCommandEncoder()->setFragmentTexture(image_view.GetHandle(), 0);
|
||||
command_recorder.GetRenderCommandEncoder()->setFragmentSamplerState(sampler.GetHandle(), 0);
|
||||
command_recorder.SetFragmentTexture(image_view.GetHandle(), 0);
|
||||
command_recorder.SetFragmentSamplerState(sampler.GetHandle(), 0);
|
||||
}
|
||||
|
||||
void GraphicsPipeline::MakePipeline(MTL::RenderPassDescriptor* render_pass) {
|
||||
|
|
|
@ -51,9 +51,9 @@ void RendererMetal::Composite(std::span<const Tegra::FramebufferConfig> framebuf
|
|||
return;
|
||||
}
|
||||
MTL::Texture* src_texture = framebuffer->GetHandle()->colorAttachments()->object(0)->texture();
|
||||
command_recorder.GetRenderCommandEncoder()->setRenderPipelineState(blit_pipeline_state);
|
||||
command_recorder.GetRenderCommandEncoder()->setFragmentTexture(src_texture, 0);
|
||||
command_recorder.GetRenderCommandEncoder()->setFragmentSamplerState(blit_sampler_state, 0);
|
||||
command_recorder.SetRenderPipelineState(blit_pipeline_state);
|
||||
command_recorder.SetFragmentTexture(src_texture, 0);
|
||||
command_recorder.SetFragmentSamplerState(blit_sampler_state, 0);
|
||||
|
||||
// Draw a full screen triangle which will get clipped to a rectangle
|
||||
command_recorder.GetRenderCommandEncoder()->drawPrimitives(MTL::PrimitiveTypeTriangle,
|
||||
|
|
Loading…
Reference in New Issue