create vertex descriptor
Some checks are pending
codespell / Check for spelling errors (push) Waiting to run
suyu verify / Verify Format (push) Waiting to run
suyu verify / test build (push) Blocked by required conditions
suyu verify / android (push) Blocked by required conditions

This commit is contained in:
Samuliak 2024-10-05 21:29:25 +02:00
parent 0b12e22331
commit 5b9a9f3077
No known key found for this signature in database
3 changed files with 209 additions and 8 deletions

View file

@ -145,4 +145,172 @@ inline size_t GetTextureBytesPerRow(VideoCore::Surface::PixelFormat pixel_format
format_info.bytes_per_block; format_info.bytes_per_block;
} }
inline MTL::VertexFormat VertexFormat(Maxwell::VertexAttribute::Type type, Maxwell::VertexAttribute::Size size) {
const MTL::VertexFormat format{([&]() {
switch (type) {
case Maxwell::VertexAttribute::Type::UnusedEnumDoNotUseBecauseItWillGoAway:
ASSERT_MSG(false, "Invalid vertex attribute type!");
break;
case Maxwell::VertexAttribute::Type::UNorm:
switch (size) {
case Maxwell::VertexAttribute::Size::Size_R8:
case Maxwell::VertexAttribute::Size::Size_A8:
return MTL::VertexFormatUCharNormalized;
case Maxwell::VertexAttribute::Size::Size_R8_G8:
case Maxwell::VertexAttribute::Size::Size_G8_R8:
return MTL::VertexFormatUChar2Normalized;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
return MTL::VertexFormatUChar3Normalized;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
return MTL::VertexFormatUChar4Normalized;
case Maxwell::VertexAttribute::Size::Size_R16:
return MTL::VertexFormatUShortNormalized;
case Maxwell::VertexAttribute::Size::Size_R16_G16:
return MTL::VertexFormatUShort2Normalized;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
return MTL::VertexFormatUShort3Normalized;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return MTL::VertexFormatUShort4Normalized;
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
return MTL::VertexFormatInvalid; // TODO: emulate
default:
break;
}
break;
case Maxwell::VertexAttribute::Type::SNorm:
switch (size) {
case Maxwell::VertexAttribute::Size::Size_R8:
case Maxwell::VertexAttribute::Size::Size_A8:
return MTL::VertexFormatCharNormalized;
case Maxwell::VertexAttribute::Size::Size_R8_G8:
case Maxwell::VertexAttribute::Size::Size_G8_R8:
return MTL::VertexFormatChar2Normalized;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
return MTL::VertexFormatChar3Normalized;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
return MTL::VertexFormatChar4Normalized;
case Maxwell::VertexAttribute::Size::Size_R16:
return MTL::VertexFormatShortNormalized;
case Maxwell::VertexAttribute::Size::Size_R16_G16:
return MTL::VertexFormatShort2Normalized;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
return MTL::VertexFormatShort3Normalized;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return MTL::VertexFormatShort4Normalized;
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
return MTL::VertexFormatInvalid; // TODO: emulate
default:
break;
}
break;
case Maxwell::VertexAttribute::Type::UInt:
case Maxwell::VertexAttribute::Type::UScaled:
switch (size) {
case Maxwell::VertexAttribute::Size::Size_R8:
case Maxwell::VertexAttribute::Size::Size_A8:
return MTL::VertexFormatUChar;
case Maxwell::VertexAttribute::Size::Size_R8_G8:
case Maxwell::VertexAttribute::Size::Size_G8_R8:
return MTL::VertexFormatUChar2;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
return MTL::VertexFormatUChar3;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
return MTL::VertexFormatUChar4;
case Maxwell::VertexAttribute::Size::Size_R16:
return MTL::VertexFormatUShort;
case Maxwell::VertexAttribute::Size::Size_R16_G16:
return MTL::VertexFormatUShort2;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
return MTL::VertexFormatUShort3;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return MTL::VertexFormatUShort4;
case Maxwell::VertexAttribute::Size::Size_R32:
return MTL::VertexFormatUInt;
case Maxwell::VertexAttribute::Size::Size_R32_G32:
return MTL::VertexFormatUInt2;
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
return MTL::VertexFormatUInt3;
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
return MTL::VertexFormatUInt4;
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
return MTL::VertexFormatInvalid; // TODO: emulate
default:
break;
}
break;
case Maxwell::VertexAttribute::Type::SInt:
case Maxwell::VertexAttribute::Type::SScaled:
switch (size) {
case Maxwell::VertexAttribute::Size::Size_R8:
case Maxwell::VertexAttribute::Size::Size_A8:
return MTL::VertexFormatChar;
case Maxwell::VertexAttribute::Size::Size_R8_G8:
case Maxwell::VertexAttribute::Size::Size_G8_R8:
return MTL::VertexFormatChar2;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8:
return MTL::VertexFormatChar3;
case Maxwell::VertexAttribute::Size::Size_R8_G8_B8_A8:
case Maxwell::VertexAttribute::Size::Size_X8_B8_G8_R8:
return MTL::VertexFormatChar4;
case Maxwell::VertexAttribute::Size::Size_R16:
return MTL::VertexFormatShort;
case Maxwell::VertexAttribute::Size::Size_R16_G16:
return MTL::VertexFormatShort2;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
return MTL::VertexFormatShort3;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return MTL::VertexFormatShort4;
case Maxwell::VertexAttribute::Size::Size_R32:
return MTL::VertexFormatInt;
case Maxwell::VertexAttribute::Size::Size_R32_G32:
return MTL::VertexFormatInt2;
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
return MTL::VertexFormatInt3;
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
return MTL::VertexFormatInt4;
case Maxwell::VertexAttribute::Size::Size_A2_B10_G10_R10:
return MTL::VertexFormatInvalid; // TODO: emulate
default:
break;
}
break;
case Maxwell::VertexAttribute::Type::Float:
switch (size) {
case Maxwell::VertexAttribute::Size::Size_R16:
return MTL::VertexFormatHalf;
case Maxwell::VertexAttribute::Size::Size_R16_G16:
return MTL::VertexFormatHalf2;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16:
return MTL::VertexFormatHalf3;
case Maxwell::VertexAttribute::Size::Size_R16_G16_B16_A16:
return MTL::VertexFormatHalf4;
case Maxwell::VertexAttribute::Size::Size_R32:
return MTL::VertexFormatFloat;
case Maxwell::VertexAttribute::Size::Size_R32_G32:
return MTL::VertexFormatFloat2;
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32:
return MTL::VertexFormatFloat3;
case Maxwell::VertexAttribute::Size::Size_R32_G32_B32_A32:
return MTL::VertexFormatFloat4;
case Maxwell::VertexAttribute::Size::Size_B10_G11_R11:
return MTL::VertexFormatInvalid; // TODO: emulate
default:
break;
}
break;
}
return MTL::VertexFormatInvalid;
})()};
if (format == MTL::VertexFormatInvalid) {
UNIMPLEMENTED_MSG("Unimplemented vertex format of type={} and size={}", type, size);
}
return format;
}
} // namespace Metal::MaxwellToMTL } // namespace Metal::MaxwellToMTL

View file

@ -18,6 +18,7 @@
#include "video_core/shader_notify.h" #include "video_core/shader_notify.h"
#include "video_core/texture_cache/texture_cache.h" #include "video_core/texture_cache/texture_cache.h"
#include "video_core/texture_cache/texture_cache_base.h" #include "video_core/texture_cache/texture_cache_base.h"
#include "video_core/renderer_metal/maxwell_to_mtl.h"
namespace Metal { namespace Metal {
namespace { namespace {
@ -56,7 +57,6 @@ GraphicsPipeline::GraphicsPipeline(const Device& device_, CommandRecorder& comma
LOG_DEBUG(Render_Metal, "framebuffer not available"); LOG_DEBUG(Render_Metal, "framebuffer not available");
return; return;
} }
MakePipeline(framebuffer->GetHandle());
} }
void GraphicsPipeline::Configure(bool is_indexed) { void GraphicsPipeline::Configure(bool is_indexed) {
@ -203,16 +203,47 @@ void GraphicsPipeline::Configure(bool is_indexed) {
} }
command_recorder.BeginOrContinueRenderPass(framebuffer->GetHandle()); command_recorder.BeginOrContinueRenderPass(framebuffer->GetHandle());
MakePipeline(framebuffer->GetHandle());
command_recorder.SetRenderPipelineState(pipeline_state); command_recorder.SetRenderPipelineState(pipeline_state);
} }
void GraphicsPipeline::MakePipeline(MTL::RenderPassDescriptor* render_pass) { void GraphicsPipeline::MakePipeline(MTL::RenderPassDescriptor* render_pass) {
MTL::RenderPipelineDescriptor* pipeline_descriptor = const auto& regs{maxwell3d->regs};
// Shader stages
MTL::RenderPipelineDescriptor* desc =
MTL::RenderPipelineDescriptor::alloc()->init(); MTL::RenderPipelineDescriptor::alloc()->init();
pipeline_descriptor->setVertexFunction(functions[0]); desc->setVertexFunction(functions[0]);
pipeline_descriptor->setFragmentFunction(functions[4]); desc->setFragmentFunction(functions[4]);
// pipeline_descriptor->setVertexDescriptor(vertex_descriptor);
// TODO: get the attachment count from render pass descriptor // Vertex descriptor
MTL::VertexDescriptor* vertex_descriptor = MTL::VertexDescriptor::alloc()->init();
for (size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
const auto& array = regs.vertex_streams[index];
if (!array.enable)
continue;
ASSERT(index < MAX_BUFFERS);
// TODO: instancing
auto layout = vertex_descriptor->layouts()->object(index);
layout->setStride(array.stride.Value());
}
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
const auto& input = regs.vertex_attrib_format[index];
// TODO: doesn't this need some special handling?
if (input.constant)
continue;
auto attribute = vertex_descriptor->attributes()->object(index);
attribute->setBufferIndex(input.buffer);
attribute->setOffset(input.offset);
attribute->setFormat(MaxwellToMTL::VertexFormat(input.type.Value(), input.size.Value()));
}
desc->setVertexDescriptor(vertex_descriptor);
vertex_descriptor->release();
// Color attachments
for (u32 index = 0; index < NUM_RT; index++) { for (u32 index = 0; index < NUM_RT; index++) {
auto* render_pass_attachment = render_pass->colorAttachments()->object(index); auto* render_pass_attachment = render_pass->colorAttachments()->object(index);
// TODO: is this the correct way to check if the attachment is valid? // TODO: is this the correct way to check if the attachment is valid?
@ -220,13 +251,14 @@ void GraphicsPipeline::MakePipeline(MTL::RenderPassDescriptor* render_pass) {
continue; continue;
} }
auto* color_attachment = pipeline_descriptor->colorAttachments()->object(index); auto* color_attachment = desc->colorAttachments()->object(index);
color_attachment->setPixelFormat(render_pass_attachment->texture()->pixelFormat()); color_attachment->setPixelFormat(render_pass_attachment->texture()->pixelFormat());
// TODO: provide blend information // TODO: provide blend information
} }
NS::Error* error = nullptr; NS::Error* error = nullptr;
pipeline_state = device.GetDevice()->newRenderPipelineState(pipeline_descriptor, &error); pipeline_state = device.GetDevice()->newRenderPipelineState(desc, &error);
desc->release();
if (error) { if (error) {
LOG_ERROR(Render_Metal, "failed to create pipeline state: {}", LOG_ERROR(Render_Metal, "failed to create pipeline state: {}",
error->description()->cString(NS::ASCIIStringEncoding)); error->description()->cString(NS::ASCIIStringEncoding));

View file

@ -118,6 +118,7 @@ private:
VideoCommon::UniformBufferSizes uniform_buffer_sizes{}; VideoCommon::UniformBufferSizes uniform_buffer_sizes{};
// u32 num_textures{}; // u32 num_textures{};
// TODO: cache pipelines if state changes
MTL::RenderPipelineState* pipeline_state{nullptr}; MTL::RenderPipelineState* pipeline_state{nullptr};
}; };