Format: src/backend/metal
This commit is contained in:
parent
2d62a371ee
commit
f58d84d488
|
@ -18,17 +18,15 @@
|
|||
#include "backend/BlendState.h"
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
class BlendState : public BlendStateBase {
|
||||
public:
|
||||
BlendState(BlendStateBuilder* builder);
|
||||
public:
|
||||
BlendState(BlendStateBuilder* builder);
|
||||
|
||||
void ApplyBlendState(MTLRenderPipelineColorAttachmentDescriptor* descriptor) const;
|
||||
void ApplyBlendState(MTLRenderPipelineColorAttachmentDescriptor* descriptor) const;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
||||
#endif // BACKEND_METAL_BLENDSTATEMTL_H_
|
||||
#endif // BACKEND_METAL_BLENDSTATEMTL_H_
|
||||
|
|
|
@ -16,13 +16,12 @@
|
|||
|
||||
#include "backend/metal/MetalBackend.h"
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
namespace {
|
||||
|
||||
MTLBlendFactor MetalBlendFactor(nxt::BlendFactor factor, bool alpha) {
|
||||
switch(factor) {
|
||||
switch (factor) {
|
||||
case nxt::BlendFactor::Zero:
|
||||
return MTLBlendFactorZero;
|
||||
case nxt::BlendFactor::One:
|
||||
|
@ -48,12 +47,13 @@ namespace metal {
|
|||
case nxt::BlendFactor::BlendColor:
|
||||
return alpha ? MTLBlendFactorBlendAlpha : MTLBlendFactorBlendColor;
|
||||
case nxt::BlendFactor::OneMinusBlendColor:
|
||||
return alpha ? MTLBlendFactorOneMinusBlendAlpha : MTLBlendFactorOneMinusBlendColor;
|
||||
return alpha ? MTLBlendFactorOneMinusBlendAlpha
|
||||
: MTLBlendFactorOneMinusBlendColor;
|
||||
}
|
||||
}
|
||||
|
||||
MTLBlendOperation MetalBlendOperation(nxt::BlendOperation operation) {
|
||||
switch(operation) {
|
||||
switch (operation) {
|
||||
case nxt::BlendOperation::Add:
|
||||
return MTLBlendOperationAdd;
|
||||
case nxt::BlendOperation::Subtract:
|
||||
|
@ -68,14 +68,19 @@ namespace metal {
|
|||
}
|
||||
|
||||
MTLColorWriteMask MetalColorWriteMask(nxt::ColorWriteMask colorWriteMask) {
|
||||
return (
|
||||
((colorWriteMask & nxt::ColorWriteMask::Red) != nxt::ColorWriteMask::None ? MTLColorWriteMaskRed : MTLColorWriteMaskNone) |
|
||||
((colorWriteMask & nxt::ColorWriteMask::Green) != nxt::ColorWriteMask::None ? MTLColorWriteMaskGreen : MTLColorWriteMaskNone) |
|
||||
((colorWriteMask & nxt::ColorWriteMask::Blue) != nxt::ColorWriteMask::None ? MTLColorWriteMaskBlue : MTLColorWriteMaskNone) |
|
||||
((colorWriteMask & nxt::ColorWriteMask::Alpha) != nxt::ColorWriteMask::None ? MTLColorWriteMaskAlpha : MTLColorWriteMaskNone)
|
||||
);
|
||||
return (((colorWriteMask & nxt::ColorWriteMask::Red) != nxt::ColorWriteMask::None
|
||||
? MTLColorWriteMaskRed
|
||||
: MTLColorWriteMaskNone) |
|
||||
((colorWriteMask & nxt::ColorWriteMask::Green) != nxt::ColorWriteMask::None
|
||||
? MTLColorWriteMaskGreen
|
||||
: MTLColorWriteMaskNone) |
|
||||
((colorWriteMask & nxt::ColorWriteMask::Blue) != nxt::ColorWriteMask::None
|
||||
? MTLColorWriteMaskBlue
|
||||
: MTLColorWriteMaskNone) |
|
||||
((colorWriteMask & nxt::ColorWriteMask::Alpha) != nxt::ColorWriteMask::None
|
||||
? MTLColorWriteMaskAlpha
|
||||
: MTLColorWriteMaskNone));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BlendState::BlendState(BlendStateBuilder* builder) : BlendStateBase(builder) {
|
||||
|
@ -92,5 +97,5 @@ namespace metal {
|
|||
descriptor.alphaBlendOperation = MetalBlendOperation(info.alphaBlend.operation);
|
||||
descriptor.writeMask = MetalColorWriteMask(info.colorWriteMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace backend::metal
|
||||
|
|
|
@ -20,54 +20,53 @@
|
|||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
class Device;
|
||||
|
||||
class Buffer : public BufferBase {
|
||||
public:
|
||||
Buffer(BufferBuilder* builder);
|
||||
~Buffer();
|
||||
public:
|
||||
Buffer(BufferBuilder* builder);
|
||||
~Buffer();
|
||||
|
||||
id<MTLBuffer> GetMTLBuffer();
|
||||
id<MTLBuffer> GetMTLBuffer();
|
||||
|
||||
void OnMapReadCommandSerialFinished(uint32_t mapSerial, uint32_t offset);
|
||||
void OnMapReadCommandSerialFinished(uint32_t mapSerial, uint32_t offset);
|
||||
|
||||
private:
|
||||
void SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) override;
|
||||
void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
|
||||
void UnmapImpl() override;
|
||||
void TransitionUsageImpl(nxt::BufferUsageBit currentUsage, nxt::BufferUsageBit targetUsage) override;
|
||||
private:
|
||||
void SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) override;
|
||||
void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
|
||||
void UnmapImpl() override;
|
||||
void TransitionUsageImpl(nxt::BufferUsageBit currentUsage,
|
||||
nxt::BufferUsageBit targetUsage) override;
|
||||
|
||||
id<MTLBuffer> mMtlBuffer = nil;
|
||||
id<MTLBuffer> mMtlBuffer = nil;
|
||||
};
|
||||
|
||||
class BufferView : public BufferViewBase {
|
||||
public:
|
||||
BufferView(BufferViewBuilder* builder);
|
||||
public:
|
||||
BufferView(BufferViewBuilder* builder);
|
||||
};
|
||||
|
||||
class MapReadRequestTracker {
|
||||
public:
|
||||
MapReadRequestTracker(Device* device);
|
||||
~MapReadRequestTracker();
|
||||
public:
|
||||
MapReadRequestTracker(Device* device);
|
||||
~MapReadRequestTracker();
|
||||
|
||||
void Track(Buffer* buffer, uint32_t mapSerial, uint32_t offset);
|
||||
void Tick(Serial finishedSerial);
|
||||
void Track(Buffer* buffer, uint32_t mapSerial, uint32_t offset);
|
||||
void Tick(Serial finishedSerial);
|
||||
|
||||
private:
|
||||
Device* mDevice;
|
||||
private:
|
||||
Device* mDevice;
|
||||
|
||||
struct Request {
|
||||
Ref<Buffer> buffer;
|
||||
uint32_t mapSerial;
|
||||
uint32_t offset;
|
||||
};
|
||||
SerialQueue<Request> mInflightRequests;
|
||||
struct Request {
|
||||
Ref<Buffer> buffer;
|
||||
uint32_t mapSerial;
|
||||
uint32_t offset;
|
||||
};
|
||||
SerialQueue<Request> mInflightRequests;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
||||
#endif // BACKEND_METAL_BUFFERMTL_H_
|
||||
#endif // BACKEND_METAL_BUFFERMTL_H_
|
||||
|
|
|
@ -17,12 +17,9 @@
|
|||
#include "backend/metal/MetalBackend.h"
|
||||
#include "backend/metal/ResourceUploader.h"
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
|
||||
Buffer::Buffer(BufferBuilder* builder)
|
||||
: BufferBase(builder) {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
Buffer::Buffer(BufferBuilder* builder) : BufferBase(builder) {
|
||||
MTLResourceOptions storageMode;
|
||||
if (GetAllowedUsage() & (nxt::BufferUsageBit::MapRead | nxt::BufferUsageBit::MapWrite)) {
|
||||
storageMode = MTLResourceStorageModeShared;
|
||||
|
@ -31,7 +28,7 @@ namespace metal {
|
|||
}
|
||||
|
||||
mMtlBuffer = [ToBackend(GetDevice())->GetMTLDevice() newBufferWithLength:GetSize()
|
||||
options:storageMode];
|
||||
options:storageMode];
|
||||
}
|
||||
|
||||
Buffer::~Buffer() {
|
||||
|
@ -50,7 +47,8 @@ namespace metal {
|
|||
|
||||
void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) {
|
||||
auto* uploader = ToBackend(GetDevice())->GetResourceUploader();
|
||||
uploader->BufferSubData(mMtlBuffer, start * sizeof(uint32_t), count * sizeof(uint32_t), data);
|
||||
uploader->BufferSubData(mMtlBuffer, start * sizeof(uint32_t), count * sizeof(uint32_t),
|
||||
data);
|
||||
}
|
||||
|
||||
void Buffer::MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t) {
|
||||
|
@ -65,12 +63,10 @@ namespace metal {
|
|||
void Buffer::TransitionUsageImpl(nxt::BufferUsageBit, nxt::BufferUsageBit) {
|
||||
}
|
||||
|
||||
BufferView::BufferView(BufferViewBuilder* builder)
|
||||
: BufferViewBase(builder) {
|
||||
BufferView::BufferView(BufferViewBuilder* builder) : BufferViewBase(builder) {
|
||||
}
|
||||
|
||||
MapReadRequestTracker::MapReadRequestTracker(Device* device)
|
||||
: mDevice(device) {
|
||||
MapReadRequestTracker::MapReadRequestTracker(Device* device) : mDevice(device) {
|
||||
}
|
||||
|
||||
MapReadRequestTracker::~MapReadRequestTracker() {
|
||||
|
@ -92,5 +88,5 @@ namespace metal {
|
|||
}
|
||||
mInflightRequests.ClearUpTo(finishedSerial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace backend::metal
|
||||
|
|
|
@ -19,24 +19,22 @@
|
|||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
class Device;
|
||||
|
||||
class CommandBuffer : public CommandBufferBase {
|
||||
public:
|
||||
CommandBuffer(CommandBufferBuilder* builder);
|
||||
~CommandBuffer();
|
||||
public:
|
||||
CommandBuffer(CommandBufferBuilder* builder);
|
||||
~CommandBuffer();
|
||||
|
||||
void FillCommands(id<MTLCommandBuffer> commandBuffer);
|
||||
void FillCommands(id<MTLCommandBuffer> commandBuffer);
|
||||
|
||||
private:
|
||||
Device* mDevice;
|
||||
CommandIterator mCommands;
|
||||
private:
|
||||
Device* mDevice;
|
||||
CommandIterator mCommands;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
||||
#endif // BACKEND_METAL_COMMANDBUFFERMTL_H_
|
||||
#endif // BACKEND_METAL_COMMANDBUFFERMTL_H_
|
||||
|
|
|
@ -25,8 +25,7 @@
|
|||
#include "backend/metal/SamplerMTL.h"
|
||||
#include "backend/metal/TextureMTL.h"
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
namespace {
|
||||
struct CurrentEncoders {
|
||||
|
@ -77,7 +76,8 @@ namespace metal {
|
|||
|
||||
const auto& info = currentRenderPass->GetSubpassInfo(subpass);
|
||||
|
||||
MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
|
||||
MTLRenderPassDescriptor* descriptor =
|
||||
[MTLRenderPassDescriptor renderPassDescriptor];
|
||||
for (unsigned int location : IterateBitSet(info.colorAttachmentsSet)) {
|
||||
uint32_t attachment = info.colorAttachments[location];
|
||||
const auto& attachmentInfo = currentRenderPass->GetAttachmentInfo(attachment);
|
||||
|
@ -90,7 +90,9 @@ namespace metal {
|
|||
if (isFirstUse && shouldClearOnFirstUse) {
|
||||
auto clearValue = currentFramebuffer->GetClearColor(location);
|
||||
descriptor.colorAttachments[location].loadAction = MTLLoadActionClear;
|
||||
descriptor.colorAttachments[location].clearColor = MTLClearColorMake(clearValue.color[0], clearValue.color[1], clearValue.color[2], clearValue.color[3]);
|
||||
descriptor.colorAttachments[location].clearColor =
|
||||
MTLClearColorMake(clearValue.color[0], clearValue.color[1],
|
||||
clearValue.color[2], clearValue.color[3]);
|
||||
} else {
|
||||
descriptor.colorAttachments[location].loadAction = MTLLoadActionLoad;
|
||||
}
|
||||
|
@ -113,7 +115,8 @@ namespace metal {
|
|||
descriptor.depthAttachment.texture = texture;
|
||||
descriptor.depthAttachment.storeAction = MTLStoreActionStore;
|
||||
|
||||
bool shouldClearDepthOnFirstUse = attachmentInfo.depthLoadOp == nxt::LoadOp::Clear;
|
||||
bool shouldClearDepthOnFirstUse =
|
||||
attachmentInfo.depthLoadOp == nxt::LoadOp::Clear;
|
||||
if (isFirstUse && shouldClearDepthOnFirstUse) {
|
||||
descriptor.depthAttachment.loadAction = MTLLoadActionClear;
|
||||
descriptor.depthAttachment.clearDepth = clearValues.depth;
|
||||
|
@ -126,7 +129,8 @@ namespace metal {
|
|||
descriptor.stencilAttachment.texture = texture;
|
||||
descriptor.stencilAttachment.storeAction = MTLStoreActionStore;
|
||||
|
||||
bool shouldClearStencilOnFirstUse = attachmentInfo.stencilLoadOp == nxt::LoadOp::Clear;
|
||||
bool shouldClearStencilOnFirstUse =
|
||||
attachmentInfo.stencilLoadOp == nxt::LoadOp::Clear;
|
||||
if (isFirstUse && shouldClearStencilOnFirstUse) {
|
||||
descriptor.stencilAttachment.loadAction = MTLLoadActionClear;
|
||||
descriptor.stencilAttachment.clearStencil = clearValues.stencil;
|
||||
|
@ -149,7 +153,8 @@ namespace metal {
|
|||
}
|
||||
|
||||
CommandBuffer::CommandBuffer(CommandBufferBuilder* builder)
|
||||
: CommandBufferBase(builder), mDevice(ToBackend(builder->GetDevice())),
|
||||
: CommandBufferBase(builder),
|
||||
mDevice(ToBackend(builder->GetDevice())),
|
||||
mCommands(builder->AcquireCommands()) {
|
||||
}
|
||||
|
||||
|
@ -172,431 +177,385 @@ namespace metal {
|
|||
uint32_t currentSubpass = 0;
|
||||
while (mCommands.NextCommandId(&type)) {
|
||||
switch (type) {
|
||||
case Command::BeginComputePass:
|
||||
{
|
||||
mCommands.NextCommand<BeginComputePassCmd>();
|
||||
encoders.BeginCompute(commandBuffer);
|
||||
case Command::BeginComputePass: {
|
||||
mCommands.NextCommand<BeginComputePassCmd>();
|
||||
encoders.BeginCompute(commandBuffer);
|
||||
|
||||
pushConstants[nxt::ShaderStage::Compute].fill(0);
|
||||
[encoders.compute setBytes: &pushConstants[nxt::ShaderStage::Compute]
|
||||
length: sizeof(uint32_t) * kMaxPushConstants
|
||||
atIndex: 0];
|
||||
}
|
||||
break;
|
||||
pushConstants[nxt::ShaderStage::Compute].fill(0);
|
||||
[encoders.compute setBytes:&pushConstants[nxt::ShaderStage::Compute]
|
||||
length:sizeof(uint32_t) * kMaxPushConstants
|
||||
atIndex:0];
|
||||
} break;
|
||||
|
||||
case Command::BeginRenderPass:
|
||||
{
|
||||
BeginRenderPassCmd* beginRenderPassCmd = mCommands.NextCommand<BeginRenderPassCmd>();
|
||||
encoders.currentRenderPass = ToBackend(beginRenderPassCmd->renderPass.Get());
|
||||
encoders.currentFramebuffer = ToBackend(beginRenderPassCmd->framebuffer.Get());
|
||||
encoders.EnsureNoBlitEncoder();
|
||||
currentSubpass = 0;
|
||||
}
|
||||
break;
|
||||
case Command::BeginRenderPass: {
|
||||
BeginRenderPassCmd* beginRenderPassCmd =
|
||||
mCommands.NextCommand<BeginRenderPassCmd>();
|
||||
encoders.currentRenderPass = ToBackend(beginRenderPassCmd->renderPass.Get());
|
||||
encoders.currentFramebuffer = ToBackend(beginRenderPassCmd->framebuffer.Get());
|
||||
encoders.EnsureNoBlitEncoder();
|
||||
currentSubpass = 0;
|
||||
} break;
|
||||
|
||||
case Command::BeginRenderSubpass:
|
||||
{
|
||||
mCommands.NextCommand<BeginRenderSubpassCmd>();
|
||||
encoders.BeginSubpass(commandBuffer, currentSubpass);
|
||||
case Command::BeginRenderSubpass: {
|
||||
mCommands.NextCommand<BeginRenderSubpassCmd>();
|
||||
encoders.BeginSubpass(commandBuffer, currentSubpass);
|
||||
|
||||
pushConstants[nxt::ShaderStage::Vertex].fill(0);
|
||||
pushConstants[nxt::ShaderStage::Fragment].fill(0);
|
||||
pushConstants[nxt::ShaderStage::Vertex].fill(0);
|
||||
pushConstants[nxt::ShaderStage::Fragment].fill(0);
|
||||
|
||||
[encoders.render setVertexBytes: &pushConstants[nxt::ShaderStage::Vertex]
|
||||
length: sizeof(uint32_t) * kMaxPushConstants
|
||||
atIndex: 0];
|
||||
[encoders.render setFragmentBytes: &pushConstants[nxt::ShaderStage::Fragment]
|
||||
length: sizeof(uint32_t) * kMaxPushConstants
|
||||
atIndex: 0];
|
||||
}
|
||||
break;
|
||||
[encoders.render setVertexBytes:&pushConstants[nxt::ShaderStage::Vertex]
|
||||
length:sizeof(uint32_t) * kMaxPushConstants
|
||||
atIndex:0];
|
||||
[encoders.render setFragmentBytes:&pushConstants[nxt::ShaderStage::Fragment]
|
||||
length:sizeof(uint32_t) * kMaxPushConstants
|
||||
atIndex:0];
|
||||
} break;
|
||||
|
||||
case Command::CopyBufferToBuffer:
|
||||
{
|
||||
CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>();
|
||||
auto& src = copy->source;
|
||||
auto& dst = copy->destination;
|
||||
case Command::CopyBufferToBuffer: {
|
||||
CopyBufferToBufferCmd* copy = mCommands.NextCommand<CopyBufferToBufferCmd>();
|
||||
auto& src = copy->source;
|
||||
auto& dst = copy->destination;
|
||||
|
||||
encoders.EnsureBlit(commandBuffer);
|
||||
[encoders.blit
|
||||
copyFromBuffer:ToBackend(src.buffer)->GetMTLBuffer()
|
||||
sourceOffset:src.offset
|
||||
toBuffer:ToBackend(dst.buffer)->GetMTLBuffer()
|
||||
destinationOffset:dst.offset
|
||||
size:copy->size];
|
||||
}
|
||||
break;
|
||||
encoders.EnsureBlit(commandBuffer);
|
||||
[encoders.blit copyFromBuffer:ToBackend(src.buffer)->GetMTLBuffer()
|
||||
sourceOffset:src.offset
|
||||
toBuffer:ToBackend(dst.buffer)->GetMTLBuffer()
|
||||
destinationOffset:dst.offset
|
||||
size:copy->size];
|
||||
} break;
|
||||
|
||||
case Command::CopyBufferToTexture:
|
||||
{
|
||||
CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>();
|
||||
auto& src = copy->source;
|
||||
auto& dst = copy->destination;
|
||||
Buffer* buffer = ToBackend(src.buffer.Get());
|
||||
Texture* texture = ToBackend(dst.texture.Get());
|
||||
case Command::CopyBufferToTexture: {
|
||||
CopyBufferToTextureCmd* copy = mCommands.NextCommand<CopyBufferToTextureCmd>();
|
||||
auto& src = copy->source;
|
||||
auto& dst = copy->destination;
|
||||
Buffer* buffer = ToBackend(src.buffer.Get());
|
||||
Texture* texture = ToBackend(dst.texture.Get());
|
||||
|
||||
MTLOrigin origin;
|
||||
origin.x = dst.x;
|
||||
origin.y = dst.y;
|
||||
origin.z = dst.z;
|
||||
MTLOrigin origin;
|
||||
origin.x = dst.x;
|
||||
origin.y = dst.y;
|
||||
origin.z = dst.z;
|
||||
|
||||
MTLSize size;
|
||||
size.width = dst.width;
|
||||
size.height = dst.height;
|
||||
size.depth = dst.depth;
|
||||
MTLSize size;
|
||||
size.width = dst.width;
|
||||
size.height = dst.height;
|
||||
size.depth = dst.depth;
|
||||
|
||||
encoders.EnsureBlit(commandBuffer);
|
||||
[encoders.blit
|
||||
copyFromBuffer:buffer->GetMTLBuffer()
|
||||
sourceOffset:src.offset
|
||||
sourceBytesPerRow:copy->rowPitch
|
||||
sourceBytesPerImage:(copy->rowPitch * dst.height)
|
||||
sourceSize:size
|
||||
toTexture:texture->GetMTLTexture()
|
||||
destinationSlice:0
|
||||
destinationLevel:dst.level
|
||||
destinationOrigin:origin];
|
||||
}
|
||||
break;
|
||||
encoders.EnsureBlit(commandBuffer);
|
||||
[encoders.blit copyFromBuffer:buffer->GetMTLBuffer()
|
||||
sourceOffset:src.offset
|
||||
sourceBytesPerRow:copy->rowPitch
|
||||
sourceBytesPerImage:(copy->rowPitch * dst.height)
|
||||
sourceSize:size
|
||||
toTexture:texture->GetMTLTexture()
|
||||
destinationSlice:0
|
||||
destinationLevel:dst.level
|
||||
destinationOrigin:origin];
|
||||
} break;
|
||||
|
||||
case Command::CopyTextureToBuffer:
|
||||
{
|
||||
CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>();
|
||||
auto& src = copy->source;
|
||||
auto& dst = copy->destination;
|
||||
Texture* texture = ToBackend(src.texture.Get());
|
||||
Buffer* buffer = ToBackend(dst.buffer.Get());
|
||||
case Command::CopyTextureToBuffer: {
|
||||
CopyTextureToBufferCmd* copy = mCommands.NextCommand<CopyTextureToBufferCmd>();
|
||||
auto& src = copy->source;
|
||||
auto& dst = copy->destination;
|
||||
Texture* texture = ToBackend(src.texture.Get());
|
||||
Buffer* buffer = ToBackend(dst.buffer.Get());
|
||||
|
||||
MTLOrigin origin;
|
||||
origin.x = src.x;
|
||||
origin.y = src.y;
|
||||
origin.z = src.z;
|
||||
MTLOrigin origin;
|
||||
origin.x = src.x;
|
||||
origin.y = src.y;
|
||||
origin.z = src.z;
|
||||
|
||||
MTLSize size;
|
||||
size.width = src.width;
|
||||
size.height = src.height;
|
||||
size.depth = src.depth;
|
||||
MTLSize size;
|
||||
size.width = src.width;
|
||||
size.height = src.height;
|
||||
size.depth = src.depth;
|
||||
|
||||
encoders.EnsureBlit(commandBuffer);
|
||||
[encoders.blit
|
||||
copyFromTexture:texture->GetMTLTexture()
|
||||
sourceSlice:0
|
||||
sourceLevel:src.level
|
||||
sourceOrigin:origin
|
||||
sourceSize:size
|
||||
toBuffer:buffer->GetMTLBuffer()
|
||||
destinationOffset:dst.offset
|
||||
encoders.EnsureBlit(commandBuffer);
|
||||
[encoders.blit copyFromTexture:texture->GetMTLTexture()
|
||||
sourceSlice:0
|
||||
sourceLevel:src.level
|
||||
sourceOrigin:origin
|
||||
sourceSize:size
|
||||
toBuffer:buffer->GetMTLBuffer()
|
||||
destinationOffset:dst.offset
|
||||
destinationBytesPerRow:copy->rowPitch
|
||||
destinationBytesPerImage:copy->rowPitch * src.height];
|
||||
}
|
||||
break;
|
||||
destinationBytesPerImage:copy->rowPitch * src.height];
|
||||
} break;
|
||||
|
||||
case Command::Dispatch:
|
||||
{
|
||||
DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>();
|
||||
ASSERT(encoders.compute);
|
||||
case Command::Dispatch: {
|
||||
DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>();
|
||||
ASSERT(encoders.compute);
|
||||
|
||||
[encoders.compute dispatchThreadgroups:MTLSizeMake(dispatch->x, dispatch->y, dispatch->z)
|
||||
threadsPerThreadgroup: lastComputePipeline->GetLocalWorkGroupSize()];
|
||||
}
|
||||
break;
|
||||
[encoders.compute
|
||||
dispatchThreadgroups:MTLSizeMake(dispatch->x, dispatch->y, dispatch->z)
|
||||
threadsPerThreadgroup:lastComputePipeline->GetLocalWorkGroupSize()];
|
||||
} break;
|
||||
|
||||
case Command::DrawArrays:
|
||||
{
|
||||
DrawArraysCmd* draw = mCommands.NextCommand<DrawArraysCmd>();
|
||||
case Command::DrawArrays: {
|
||||
DrawArraysCmd* draw = mCommands.NextCommand<DrawArraysCmd>();
|
||||
|
||||
ASSERT(encoders.render);
|
||||
[encoders.render
|
||||
drawPrimitives:lastRenderPipeline->GetMTLPrimitiveTopology()
|
||||
vertexStart:draw->firstVertex
|
||||
vertexCount:draw->vertexCount
|
||||
instanceCount:draw->instanceCount
|
||||
baseInstance:draw->firstInstance];
|
||||
}
|
||||
break;
|
||||
ASSERT(encoders.render);
|
||||
[encoders.render drawPrimitives:lastRenderPipeline->GetMTLPrimitiveTopology()
|
||||
vertexStart:draw->firstVertex
|
||||
vertexCount:draw->vertexCount
|
||||
instanceCount:draw->instanceCount
|
||||
baseInstance:draw->firstInstance];
|
||||
} break;
|
||||
|
||||
case Command::DrawElements:
|
||||
{
|
||||
DrawElementsCmd* draw = mCommands.NextCommand<DrawElementsCmd>();
|
||||
case Command::DrawElements: {
|
||||
DrawElementsCmd* draw = mCommands.NextCommand<DrawElementsCmd>();
|
||||
|
||||
ASSERT(encoders.render);
|
||||
[encoders.render
|
||||
drawIndexedPrimitives:lastRenderPipeline->GetMTLPrimitiveTopology()
|
||||
indexCount:draw->indexCount
|
||||
indexType:lastRenderPipeline->GetMTLIndexType()
|
||||
indexBuffer:indexBuffer
|
||||
ASSERT(encoders.render);
|
||||
[encoders.render
|
||||
drawIndexedPrimitives:lastRenderPipeline->GetMTLPrimitiveTopology()
|
||||
indexCount:draw->indexCount
|
||||
indexType:lastRenderPipeline->GetMTLIndexType()
|
||||
indexBuffer:indexBuffer
|
||||
indexBufferOffset:indexBufferOffset
|
||||
instanceCount:draw->instanceCount
|
||||
baseVertex:0
|
||||
baseInstance:draw->firstInstance];
|
||||
}
|
||||
break;
|
||||
instanceCount:draw->instanceCount
|
||||
baseVertex:0
|
||||
baseInstance:draw->firstInstance];
|
||||
} break;
|
||||
|
||||
case Command::EndComputePass:
|
||||
{
|
||||
mCommands.NextCommand<EndComputePassCmd>();
|
||||
encoders.EndCompute();
|
||||
}
|
||||
break;
|
||||
case Command::EndComputePass: {
|
||||
mCommands.NextCommand<EndComputePassCmd>();
|
||||
encoders.EndCompute();
|
||||
} break;
|
||||
|
||||
case Command::EndRenderPass:
|
||||
{
|
||||
mCommands.NextCommand<EndRenderPassCmd>();
|
||||
}
|
||||
break;
|
||||
case Command::EndRenderPass: {
|
||||
mCommands.NextCommand<EndRenderPassCmd>();
|
||||
} break;
|
||||
|
||||
case Command::EndRenderSubpass:
|
||||
{
|
||||
mCommands.NextCommand<EndRenderSubpassCmd>();
|
||||
encoders.EndSubpass();
|
||||
currentSubpass += 1;
|
||||
}
|
||||
break;
|
||||
case Command::EndRenderSubpass: {
|
||||
mCommands.NextCommand<EndRenderSubpassCmd>();
|
||||
encoders.EndSubpass();
|
||||
currentSubpass += 1;
|
||||
} break;
|
||||
|
||||
case Command::SetComputePipeline:
|
||||
{
|
||||
SetComputePipelineCmd* cmd = mCommands.NextCommand<SetComputePipelineCmd>();
|
||||
lastComputePipeline = ToBackend(cmd->pipeline).Get();
|
||||
case Command::SetComputePipeline: {
|
||||
SetComputePipelineCmd* cmd = mCommands.NextCommand<SetComputePipelineCmd>();
|
||||
lastComputePipeline = ToBackend(cmd->pipeline).Get();
|
||||
|
||||
ASSERT(encoders.compute);
|
||||
lastComputePipeline->Encode(encoders.compute);
|
||||
}
|
||||
break;
|
||||
ASSERT(encoders.compute);
|
||||
lastComputePipeline->Encode(encoders.compute);
|
||||
} break;
|
||||
|
||||
case Command::SetRenderPipeline:
|
||||
{
|
||||
SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
|
||||
lastRenderPipeline = ToBackend(cmd->pipeline).Get();
|
||||
case Command::SetRenderPipeline: {
|
||||
SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
|
||||
lastRenderPipeline = ToBackend(cmd->pipeline).Get();
|
||||
|
||||
ASSERT(encoders.render);
|
||||
DepthStencilState* depthStencilState = ToBackend(lastRenderPipeline->GetDepthStencilState());
|
||||
[encoders.render setDepthStencilState:depthStencilState->GetMTLDepthStencilState()];
|
||||
lastRenderPipeline->Encode(encoders.render);
|
||||
}
|
||||
break;
|
||||
ASSERT(encoders.render);
|
||||
DepthStencilState* depthStencilState =
|
||||
ToBackend(lastRenderPipeline->GetDepthStencilState());
|
||||
[encoders.render
|
||||
setDepthStencilState:depthStencilState->GetMTLDepthStencilState()];
|
||||
lastRenderPipeline->Encode(encoders.render);
|
||||
} break;
|
||||
|
||||
case Command::SetPushConstants:
|
||||
{
|
||||
SetPushConstantsCmd* cmd = mCommands.NextCommand<SetPushConstantsCmd>();
|
||||
uint32_t* values = mCommands.NextData<uint32_t>(cmd->count);
|
||||
case Command::SetPushConstants: {
|
||||
SetPushConstantsCmd* cmd = mCommands.NextCommand<SetPushConstantsCmd>();
|
||||
uint32_t* values = mCommands.NextData<uint32_t>(cmd->count);
|
||||
|
||||
for (auto stage : IterateStages(cmd->stages)) {
|
||||
memcpy(&pushConstants[stage][cmd->offset], values, cmd->count * sizeof(uint32_t));
|
||||
for (auto stage : IterateStages(cmd->stages)) {
|
||||
memcpy(&pushConstants[stage][cmd->offset], values,
|
||||
cmd->count * sizeof(uint32_t));
|
||||
|
||||
switch (stage) {
|
||||
case nxt::ShaderStage::Compute:
|
||||
ASSERT(encoders.compute);
|
||||
[encoders.compute setBytes: &pushConstants[nxt::ShaderStage::Compute]
|
||||
length: sizeof(uint32_t) * kMaxPushConstants
|
||||
atIndex: 0];
|
||||
break;
|
||||
case nxt::ShaderStage::Fragment:
|
||||
ASSERT(encoders.render);
|
||||
[encoders.render setFragmentBytes: &pushConstants[nxt::ShaderStage::Fragment]
|
||||
length: sizeof(uint32_t) * kMaxPushConstants
|
||||
atIndex: 0];
|
||||
break;
|
||||
case nxt::ShaderStage::Vertex:
|
||||
ASSERT(encoders.render);
|
||||
[encoders.render setVertexBytes: &pushConstants[nxt::ShaderStage::Vertex]
|
||||
length: sizeof(uint32_t) * kMaxPushConstants
|
||||
atIndex: 0];
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
switch (stage) {
|
||||
case nxt::ShaderStage::Compute:
|
||||
ASSERT(encoders.compute);
|
||||
[encoders.compute setBytes:&pushConstants[nxt::ShaderStage::Compute]
|
||||
length:sizeof(uint32_t) * kMaxPushConstants
|
||||
atIndex:0];
|
||||
break;
|
||||
case nxt::ShaderStage::Fragment:
|
||||
ASSERT(encoders.render);
|
||||
[encoders.render
|
||||
setFragmentBytes:&pushConstants[nxt::ShaderStage::Fragment]
|
||||
length:sizeof(uint32_t) * kMaxPushConstants
|
||||
atIndex:0];
|
||||
break;
|
||||
case nxt::ShaderStage::Vertex:
|
||||
ASSERT(encoders.render);
|
||||
[encoders.render
|
||||
setVertexBytes:&pushConstants[nxt::ShaderStage::Vertex]
|
||||
length:sizeof(uint32_t) * kMaxPushConstants
|
||||
atIndex:0];
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case Command::SetStencilReference:
|
||||
{
|
||||
SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
|
||||
case Command::SetStencilReference: {
|
||||
SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
|
||||
|
||||
ASSERT(encoders.render);
|
||||
ASSERT(encoders.render);
|
||||
|
||||
[encoders.render setStencilReferenceValue:cmd->reference];
|
||||
}
|
||||
break;
|
||||
[encoders.render setStencilReferenceValue:cmd->reference];
|
||||
} break;
|
||||
|
||||
case Command::SetBlendColor:
|
||||
{
|
||||
SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>();
|
||||
case Command::SetBlendColor: {
|
||||
SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>();
|
||||
|
||||
ASSERT(encoders.render);
|
||||
ASSERT(encoders.render);
|
||||
|
||||
[encoders.render
|
||||
setBlendColorRed:cmd->r
|
||||
green:cmd->g
|
||||
blue:cmd->b
|
||||
alpha:cmd->a ];
|
||||
}
|
||||
break;
|
||||
[encoders.render setBlendColorRed:cmd->r green:cmd->g blue:cmd->b alpha:cmd->a];
|
||||
} break;
|
||||
|
||||
case Command::SetBindGroup:
|
||||
{
|
||||
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
|
||||
BindGroup* group = ToBackend(cmd->group.Get());
|
||||
uint32_t groupIndex = cmd->index;
|
||||
case Command::SetBindGroup: {
|
||||
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
|
||||
BindGroup* group = ToBackend(cmd->group.Get());
|
||||
uint32_t groupIndex = cmd->index;
|
||||
|
||||
const auto& layout = group->GetLayout()->GetBindingInfo();
|
||||
const auto& layout = group->GetLayout()->GetBindingInfo();
|
||||
|
||||
// TODO(kainino@chromium.org): Maintain buffers and offsets arrays in BindGroup so that we
|
||||
// only have to do one setVertexBuffers and one setFragmentBuffers call here.
|
||||
for (size_t binding = 0; binding < layout.mask.size(); ++binding) {
|
||||
if (!layout.mask[binding]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto stage = layout.visibilities[binding];
|
||||
bool vertStage = stage & nxt::ShaderStageBit::Vertex && lastRenderPipeline != nullptr;
|
||||
bool fragStage = stage & nxt::ShaderStageBit::Fragment && lastRenderPipeline != nullptr;
|
||||
bool computeStage = stage & nxt::ShaderStageBit::Compute && lastComputePipeline != nullptr;
|
||||
uint32_t vertIndex = 0;
|
||||
uint32_t fragIndex = 0;
|
||||
uint32_t computeIndex = 0;
|
||||
if (vertStage) {
|
||||
ASSERT(lastRenderPipeline != nullptr);
|
||||
vertIndex = ToBackend(lastRenderPipeline->GetLayout())->
|
||||
GetBindingIndexInfo(nxt::ShaderStage::Vertex)[groupIndex][binding];
|
||||
}
|
||||
if (fragStage) {
|
||||
ASSERT(lastRenderPipeline != nullptr);
|
||||
fragIndex = ToBackend(lastRenderPipeline->GetLayout())->
|
||||
GetBindingIndexInfo(nxt::ShaderStage::Fragment)[groupIndex][binding];
|
||||
}
|
||||
if (computeStage) {
|
||||
ASSERT(lastComputePipeline != nullptr);
|
||||
computeIndex = ToBackend(lastComputePipeline->GetLayout())->
|
||||
GetBindingIndexInfo(nxt::ShaderStage::Compute)[groupIndex][binding];
|
||||
}
|
||||
|
||||
switch (layout.types[binding]) {
|
||||
case nxt::BindingType::UniformBuffer:
|
||||
case nxt::BindingType::StorageBuffer:
|
||||
{
|
||||
BufferView* view = ToBackend(group->GetBindingAsBufferView(binding));
|
||||
auto b = ToBackend(view->GetBuffer());
|
||||
const id<MTLBuffer> buffer = b->GetMTLBuffer();
|
||||
const NSUInteger offset = view->GetOffset();
|
||||
if (vertStage) {
|
||||
[encoders.render
|
||||
setVertexBuffers:&buffer
|
||||
offsets:&offset
|
||||
withRange:NSMakeRange(vertIndex, 1)];
|
||||
}
|
||||
if (fragStage) {
|
||||
[encoders.render
|
||||
setFragmentBuffers:&buffer
|
||||
offsets:&offset
|
||||
withRange:NSMakeRange(fragIndex, 1)];
|
||||
}
|
||||
if (computeStage) {
|
||||
[encoders.compute
|
||||
setBuffers:&buffer
|
||||
offsets:&offset
|
||||
withRange:NSMakeRange(computeIndex, 1)];
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case nxt::BindingType::Sampler:
|
||||
{
|
||||
auto sampler = ToBackend(group->GetBindingAsSampler(binding));
|
||||
if (vertStage) {
|
||||
[encoders.render
|
||||
setVertexSamplerState:sampler->GetMTLSamplerState()
|
||||
atIndex:vertIndex];
|
||||
}
|
||||
if (fragStage) {
|
||||
[encoders.render
|
||||
setFragmentSamplerState:sampler->GetMTLSamplerState()
|
||||
atIndex:fragIndex];
|
||||
}
|
||||
if (computeStage) {
|
||||
[encoders.compute
|
||||
setSamplerState:sampler->GetMTLSamplerState()
|
||||
atIndex:computeIndex];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case nxt::BindingType::SampledTexture:
|
||||
{
|
||||
auto texture = ToBackend(group->GetBindingAsTextureView(binding)->GetTexture());
|
||||
if (vertStage) {
|
||||
[encoders.render
|
||||
setVertexTexture:texture->GetMTLTexture()
|
||||
atIndex:vertIndex];
|
||||
}
|
||||
if (fragStage) {
|
||||
[encoders.render
|
||||
setFragmentTexture:texture->GetMTLTexture()
|
||||
atIndex:fragIndex];
|
||||
}
|
||||
if (computeStage) {
|
||||
[encoders.compute
|
||||
setTexture:texture->GetMTLTexture()
|
||||
atIndex:computeIndex];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::SetIndexBuffer:
|
||||
{
|
||||
SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
|
||||
auto b = ToBackend(cmd->buffer.Get());
|
||||
indexBuffer = b->GetMTLBuffer();
|
||||
indexBufferOffset = cmd->offset;
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::SetVertexBuffers:
|
||||
{
|
||||
SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
|
||||
auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
|
||||
auto offsets = mCommands.NextData<uint32_t>(cmd->count);
|
||||
|
||||
std::array<id<MTLBuffer>, kMaxVertexInputs> mtlBuffers;
|
||||
std::array<NSUInteger, kMaxVertexInputs> mtlOffsets;
|
||||
|
||||
// Perhaps an "array of vertex buffers(+offsets?)" should be
|
||||
// a NXT API primitive to avoid reconstructing this array?
|
||||
for (uint32_t i = 0; i < cmd->count; ++i) {
|
||||
Buffer* buffer = ToBackend(buffers[i].Get());
|
||||
mtlBuffers[i] = buffer->GetMTLBuffer();
|
||||
mtlOffsets[i] = offsets[i];
|
||||
// TODO(kainino@chromium.org): Maintain buffers and offsets arrays in BindGroup
|
||||
// so that we only have to do one setVertexBuffers and one setFragmentBuffers
|
||||
// call here.
|
||||
for (size_t binding = 0; binding < layout.mask.size(); ++binding) {
|
||||
if (!layout.mask[binding]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ASSERT(encoders.render);
|
||||
[encoders.render
|
||||
setVertexBuffers:mtlBuffers.data()
|
||||
offsets:mtlOffsets.data()
|
||||
withRange:NSMakeRange(kMaxBindingsPerGroup + cmd->startSlot, cmd->count)];
|
||||
auto stage = layout.visibilities[binding];
|
||||
bool vertStage =
|
||||
stage & nxt::ShaderStageBit::Vertex && lastRenderPipeline != nullptr;
|
||||
bool fragStage =
|
||||
stage & nxt::ShaderStageBit::Fragment && lastRenderPipeline != nullptr;
|
||||
bool computeStage =
|
||||
stage & nxt::ShaderStageBit::Compute && lastComputePipeline != nullptr;
|
||||
uint32_t vertIndex = 0;
|
||||
uint32_t fragIndex = 0;
|
||||
uint32_t computeIndex = 0;
|
||||
if (vertStage) {
|
||||
ASSERT(lastRenderPipeline != nullptr);
|
||||
vertIndex = ToBackend(lastRenderPipeline->GetLayout())
|
||||
->GetBindingIndexInfo(
|
||||
nxt::ShaderStage::Vertex)[groupIndex][binding];
|
||||
}
|
||||
if (fragStage) {
|
||||
ASSERT(lastRenderPipeline != nullptr);
|
||||
fragIndex = ToBackend(lastRenderPipeline->GetLayout())
|
||||
->GetBindingIndexInfo(
|
||||
nxt::ShaderStage::Fragment)[groupIndex][binding];
|
||||
}
|
||||
if (computeStage) {
|
||||
ASSERT(lastComputePipeline != nullptr);
|
||||
computeIndex = ToBackend(lastComputePipeline->GetLayout())
|
||||
->GetBindingIndexInfo(
|
||||
nxt::ShaderStage::Compute)[groupIndex][binding];
|
||||
}
|
||||
|
||||
switch (layout.types[binding]) {
|
||||
case nxt::BindingType::UniformBuffer:
|
||||
case nxt::BindingType::StorageBuffer: {
|
||||
BufferView* view =
|
||||
ToBackend(group->GetBindingAsBufferView(binding));
|
||||
auto b = ToBackend(view->GetBuffer());
|
||||
const id<MTLBuffer> buffer = b->GetMTLBuffer();
|
||||
const NSUInteger offset = view->GetOffset();
|
||||
if (vertStage) {
|
||||
[encoders.render setVertexBuffers:&buffer
|
||||
offsets:&offset
|
||||
withRange:NSMakeRange(vertIndex, 1)];
|
||||
}
|
||||
if (fragStage) {
|
||||
[encoders.render setFragmentBuffers:&buffer
|
||||
offsets:&offset
|
||||
withRange:NSMakeRange(fragIndex, 1)];
|
||||
}
|
||||
if (computeStage) {
|
||||
[encoders.compute setBuffers:&buffer
|
||||
offsets:&offset
|
||||
withRange:NSMakeRange(computeIndex, 1)];
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
case nxt::BindingType::Sampler: {
|
||||
auto sampler = ToBackend(group->GetBindingAsSampler(binding));
|
||||
if (vertStage) {
|
||||
[encoders.render
|
||||
setVertexSamplerState:sampler->GetMTLSamplerState()
|
||||
atIndex:vertIndex];
|
||||
}
|
||||
if (fragStage) {
|
||||
[encoders.render
|
||||
setFragmentSamplerState:sampler->GetMTLSamplerState()
|
||||
atIndex:fragIndex];
|
||||
}
|
||||
if (computeStage) {
|
||||
[encoders.compute setSamplerState:sampler->GetMTLSamplerState()
|
||||
atIndex:computeIndex];
|
||||
}
|
||||
} break;
|
||||
|
||||
case nxt::BindingType::SampledTexture: {
|
||||
auto texture = ToBackend(
|
||||
group->GetBindingAsTextureView(binding)->GetTexture());
|
||||
if (vertStage) {
|
||||
[encoders.render setVertexTexture:texture->GetMTLTexture()
|
||||
atIndex:vertIndex];
|
||||
}
|
||||
if (fragStage) {
|
||||
[encoders.render setFragmentTexture:texture->GetMTLTexture()
|
||||
atIndex:fragIndex];
|
||||
}
|
||||
if (computeStage) {
|
||||
[encoders.compute setTexture:texture->GetMTLTexture()
|
||||
atIndex:computeIndex];
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case Command::TransitionBufferUsage:
|
||||
{
|
||||
TransitionBufferUsageCmd* cmd = mCommands.NextCommand<TransitionBufferUsageCmd>();
|
||||
case Command::SetIndexBuffer: {
|
||||
SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
|
||||
auto b = ToBackend(cmd->buffer.Get());
|
||||
indexBuffer = b->GetMTLBuffer();
|
||||
indexBufferOffset = cmd->offset;
|
||||
} break;
|
||||
|
||||
cmd->buffer->UpdateUsageInternal(cmd->usage);
|
||||
case Command::SetVertexBuffers: {
|
||||
SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
|
||||
auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
|
||||
auto offsets = mCommands.NextData<uint32_t>(cmd->count);
|
||||
|
||||
std::array<id<MTLBuffer>, kMaxVertexInputs> mtlBuffers;
|
||||
std::array<NSUInteger, kMaxVertexInputs> mtlOffsets;
|
||||
|
||||
// Perhaps an "array of vertex buffers(+offsets?)" should be
|
||||
// a NXT API primitive to avoid reconstructing this array?
|
||||
for (uint32_t i = 0; i < cmd->count; ++i) {
|
||||
Buffer* buffer = ToBackend(buffers[i].Get());
|
||||
mtlBuffers[i] = buffer->GetMTLBuffer();
|
||||
mtlOffsets[i] = offsets[i];
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::TransitionTextureUsage:
|
||||
{
|
||||
TransitionTextureUsageCmd* cmd = mCommands.NextCommand<TransitionTextureUsageCmd>();
|
||||
ASSERT(encoders.render);
|
||||
[encoders.render
|
||||
setVertexBuffers:mtlBuffers.data()
|
||||
offsets:mtlOffsets.data()
|
||||
withRange:NSMakeRange(kMaxBindingsPerGroup + cmd->startSlot,
|
||||
cmd->count)];
|
||||
} break;
|
||||
|
||||
cmd->texture->UpdateUsageInternal(cmd->usage);
|
||||
}
|
||||
break;
|
||||
case Command::TransitionBufferUsage: {
|
||||
TransitionBufferUsageCmd* cmd =
|
||||
mCommands.NextCommand<TransitionBufferUsageCmd>();
|
||||
|
||||
cmd->buffer->UpdateUsageInternal(cmd->usage);
|
||||
} break;
|
||||
|
||||
case Command::TransitionTextureUsage: {
|
||||
TransitionTextureUsageCmd* cmd =
|
||||
mCommands.NextCommand<TransitionTextureUsageCmd>();
|
||||
|
||||
cmd->texture->UpdateUsageInternal(cmd->usage);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -605,5 +564,4 @@ namespace metal {
|
|||
ASSERT(encoders.compute == nil);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
|
|
@ -19,23 +19,21 @@
|
|||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
class ComputePipeline : public ComputePipelineBase {
|
||||
public:
|
||||
ComputePipeline(ComputePipelineBuilder* builder);
|
||||
~ComputePipeline();
|
||||
public:
|
||||
ComputePipeline(ComputePipelineBuilder* builder);
|
||||
~ComputePipeline();
|
||||
|
||||
void Encode(id<MTLComputeCommandEncoder> encoder);
|
||||
MTLSize GetLocalWorkGroupSize() const;
|
||||
void Encode(id<MTLComputeCommandEncoder> encoder);
|
||||
MTLSize GetLocalWorkGroupSize() const;
|
||||
|
||||
private:
|
||||
id<MTLComputePipelineState> mMtlComputePipelineState = nil;
|
||||
MTLSize mLocalWorkgroupSize;
|
||||
private:
|
||||
id<MTLComputePipelineState> mMtlComputePipelineState = nil;
|
||||
MTLSize mLocalWorkgroupSize;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
||||
#endif // BACKEND_METAL_COMPUTEPIPELINEMTL_H_
|
||||
#endif // BACKEND_METAL_COMPUTEPIPELINEMTL_H_
|
||||
|
|
|
@ -17,12 +17,10 @@
|
|||
#include "backend/metal/MetalBackend.h"
|
||||
#include "backend/metal/ShaderModuleMTL.h"
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
ComputePipeline::ComputePipeline(ComputePipelineBuilder* builder)
|
||||
: ComputePipelineBase(builder) {
|
||||
|
||||
auto mtlDevice = ToBackend(builder->GetDevice())->GetMTLDevice();
|
||||
|
||||
const auto& module = ToBackend(builder->GetStageInfo(nxt::ShaderStage::Compute).module);
|
||||
|
@ -30,9 +28,9 @@ namespace metal {
|
|||
|
||||
auto compilationData = module->GetFunction(entryPoint.c_str(), ToBackend(GetLayout()));
|
||||
|
||||
NSError *error = nil;
|
||||
mMtlComputePipelineState = [mtlDevice
|
||||
newComputePipelineStateWithFunction:compilationData.function error:&error];
|
||||
NSError* error = nil;
|
||||
mMtlComputePipelineState =
|
||||
[mtlDevice newComputePipelineStateWithFunction:compilationData.function error:&error];
|
||||
if (error != nil) {
|
||||
NSLog(@" error => %@", error);
|
||||
builder->HandleError("Error creating pipeline state");
|
||||
|
@ -55,5 +53,4 @@ namespace metal {
|
|||
return mLocalWorkgroupSize;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
|
|
@ -19,23 +19,21 @@
|
|||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
class Device;
|
||||
|
||||
class DepthStencilState : public DepthStencilStateBase {
|
||||
public:
|
||||
DepthStencilState(DepthStencilStateBuilder* builder);
|
||||
~DepthStencilState();
|
||||
public:
|
||||
DepthStencilState(DepthStencilStateBuilder* builder);
|
||||
~DepthStencilState();
|
||||
|
||||
id<MTLDepthStencilState> GetMTLDepthStencilState();
|
||||
id<MTLDepthStencilState> GetMTLDepthStencilState();
|
||||
|
||||
private:
|
||||
id<MTLDepthStencilState> mMtlDepthStencilState = nil;
|
||||
private:
|
||||
id<MTLDepthStencilState> mMtlDepthStencilState = nil;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
||||
#endif // BACKEND_METAL_DEPTHSTENCILSTATEMTL_H_
|
||||
#endif // BACKEND_METAL_DEPTHSTENCILSTATEMTL_H_
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
|
||||
#include "backend/metal/MetalBackend.h"
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
namespace {
|
||||
MTLCompareFunction MetalDepthStencilCompareFunction(nxt::CompareFunction compareFunction) {
|
||||
|
@ -68,7 +67,8 @@ namespace metal {
|
|||
MTLDepthStencilDescriptor* mtlDepthStencilDescriptor = [MTLDepthStencilDescriptor new];
|
||||
|
||||
auto& depth = GetDepth();
|
||||
mtlDepthStencilDescriptor.depthCompareFunction = MetalDepthStencilCompareFunction(depth.compareFunction);
|
||||
mtlDepthStencilDescriptor.depthCompareFunction =
|
||||
MetalDepthStencilCompareFunction(depth.compareFunction);
|
||||
mtlDepthStencilDescriptor.depthWriteEnabled = depth.depthWriteEnabled;
|
||||
|
||||
auto& stencil = GetStencil();
|
||||
|
@ -76,17 +76,23 @@ namespace metal {
|
|||
MTLStencilDescriptor* backFaceStencil = [MTLStencilDescriptor new];
|
||||
MTLStencilDescriptor* frontFaceStencil = [MTLStencilDescriptor new];
|
||||
|
||||
backFaceStencil.stencilCompareFunction = MetalDepthStencilCompareFunction(stencil.back.compareFunction);
|
||||
backFaceStencil.stencilFailureOperation = MetalStencilOperation(stencil.back.stencilFail);
|
||||
backFaceStencil.stencilCompareFunction =
|
||||
MetalDepthStencilCompareFunction(stencil.back.compareFunction);
|
||||
backFaceStencil.stencilFailureOperation =
|
||||
MetalStencilOperation(stencil.back.stencilFail);
|
||||
backFaceStencil.depthFailureOperation = MetalStencilOperation(stencil.back.depthFail);
|
||||
backFaceStencil.depthStencilPassOperation = MetalStencilOperation(stencil.back.depthStencilPass);
|
||||
backFaceStencil.depthStencilPassOperation =
|
||||
MetalStencilOperation(stencil.back.depthStencilPass);
|
||||
backFaceStencil.readMask = stencil.readMask;
|
||||
backFaceStencil.writeMask = stencil.writeMask;
|
||||
|
||||
frontFaceStencil.stencilCompareFunction = MetalDepthStencilCompareFunction(stencil.front.compareFunction);
|
||||
frontFaceStencil.stencilFailureOperation = MetalStencilOperation(stencil.front.stencilFail);
|
||||
frontFaceStencil.stencilCompareFunction =
|
||||
MetalDepthStencilCompareFunction(stencil.front.compareFunction);
|
||||
frontFaceStencil.stencilFailureOperation =
|
||||
MetalStencilOperation(stencil.front.stencilFail);
|
||||
frontFaceStencil.depthFailureOperation = MetalStencilOperation(stencil.front.depthFail);
|
||||
frontFaceStencil.depthStencilPassOperation = MetalStencilOperation(stencil.front.depthStencilPass);
|
||||
frontFaceStencil.depthStencilPassOperation =
|
||||
MetalStencilOperation(stencil.front.depthStencilPass);
|
||||
frontFaceStencil.readMask = stencil.readMask;
|
||||
frontFaceStencil.writeMask = stencil.writeMask;
|
||||
|
||||
|
@ -97,7 +103,8 @@ namespace metal {
|
|||
}
|
||||
|
||||
auto mtlDevice = ToBackend(builder->GetDevice())->GetMTLDevice();
|
||||
mMtlDepthStencilState = [mtlDevice newDepthStencilStateWithDescriptor:mtlDepthStencilDescriptor];
|
||||
mMtlDepthStencilState =
|
||||
[mtlDevice newDepthStencilStateWithDescriptor:mtlDepthStencilDescriptor];
|
||||
[mtlDepthStencilDescriptor release];
|
||||
}
|
||||
|
||||
|
@ -110,5 +117,4 @@ namespace metal {
|
|||
return mMtlDepthStencilState;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
|
|
@ -12,13 +12,13 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "backend/metal/MetalBackend.h"
|
||||
#include "backend/metal/BlendStateMTL.h"
|
||||
#include "backend/metal/BufferMTL.h"
|
||||
#include "backend/metal/CommandBufferMTL.h"
|
||||
#include "backend/metal/ComputePipelineMTL.h"
|
||||
#include "backend/metal/DepthStencilStateMTL.h"
|
||||
#include "backend/metal/InputStateMTL.h"
|
||||
#include "backend/metal/MetalBackend.h"
|
||||
#include "backend/metal/PipelineLayoutMTL.h"
|
||||
#include "backend/metal/RenderPipelineMTL.h"
|
||||
#include "backend/metal/SamplerMTL.h"
|
||||
|
|
|
@ -19,21 +19,19 @@
|
|||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
class InputState : public InputStateBase {
|
||||
public:
|
||||
InputState(InputStateBuilder* builder);
|
||||
~InputState();
|
||||
public:
|
||||
InputState(InputStateBuilder* builder);
|
||||
~InputState();
|
||||
|
||||
MTLVertexDescriptor* GetMTLVertexDescriptor();
|
||||
MTLVertexDescriptor* GetMTLVertexDescriptor();
|
||||
|
||||
private:
|
||||
MTLVertexDescriptor* mMtlVertexDescriptor = nil;
|
||||
private:
|
||||
MTLVertexDescriptor* mMtlVertexDescriptor = nil;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
||||
#endif // BACKEND_METAL_COMMANDINPUTSTATEMTL_H_
|
||||
#endif // BACKEND_METAL_COMMANDINPUTSTATEMTL_H_
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
#include "backend/metal/MetalBackend.h"
|
||||
#include "common/BitSetIterator.h"
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
namespace {
|
||||
MTLVertexFormat VertexFormatType(nxt::VertexFormat format) {
|
||||
|
@ -44,8 +43,7 @@ namespace metal {
|
|||
}
|
||||
}
|
||||
|
||||
InputState::InputState(InputStateBuilder* builder)
|
||||
: InputStateBase(builder) {
|
||||
InputState::InputState(InputStateBuilder* builder) : InputStateBase(builder) {
|
||||
mMtlVertexDescriptor = [MTLVertexDescriptor new];
|
||||
|
||||
const auto& attributesSetMask = GetAttributesSetMask();
|
||||
|
@ -95,5 +93,4 @@ namespace metal {
|
|||
return mMtlVertexDescriptor;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
|
|
@ -26,12 +26,11 @@
|
|||
#include "backend/ToBackend.h"
|
||||
#include "common/Serial.h"
|
||||
|
||||
#include <type_traits>
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
#include <type_traits>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
class BindGroup;
|
||||
class BindGroupLayout;
|
||||
|
@ -77,7 +76,7 @@ namespace metal {
|
|||
using TextureViewType = TextureView;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
auto ToBackend(T&& common) -> decltype(ToBackendBase<MetalBackendTraits>(common)) {
|
||||
return ToBackendBase<MetalBackendTraits>(common);
|
||||
}
|
||||
|
@ -86,91 +85,90 @@ namespace metal {
|
|||
class ResourceUploader;
|
||||
|
||||
class Device : public DeviceBase {
|
||||
public:
|
||||
Device(id<MTLDevice> mtlDevice);
|
||||
~Device();
|
||||
public:
|
||||
Device(id<MTLDevice> mtlDevice);
|
||||
~Device();
|
||||
|
||||
BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
|
||||
BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override;
|
||||
BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
|
||||
BufferBase* CreateBuffer(BufferBuilder* builder) override;
|
||||
BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
|
||||
CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override;
|
||||
ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
|
||||
DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override;
|
||||
InputStateBase* CreateInputState(InputStateBuilder* builder) override;
|
||||
FramebufferBase* CreateFramebuffer(FramebufferBuilder* builder) override;
|
||||
PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override;
|
||||
QueueBase* CreateQueue(QueueBuilder* builder) override;
|
||||
RenderPassBase* CreateRenderPass(RenderPassBuilder* builder) override;
|
||||
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
|
||||
SamplerBase* CreateSampler(SamplerBuilder* builder) override;
|
||||
ShaderModuleBase* CreateShaderModule(ShaderModuleBuilder* builder) override;
|
||||
SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
|
||||
TextureBase* CreateTexture(TextureBuilder* builder) override;
|
||||
TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override;
|
||||
BindGroupBase* CreateBindGroup(BindGroupBuilder* builder) override;
|
||||
BindGroupLayoutBase* CreateBindGroupLayout(BindGroupLayoutBuilder* builder) override;
|
||||
BlendStateBase* CreateBlendState(BlendStateBuilder* builder) override;
|
||||
BufferBase* CreateBuffer(BufferBuilder* builder) override;
|
||||
BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
|
||||
CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override;
|
||||
ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
|
||||
DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override;
|
||||
InputStateBase* CreateInputState(InputStateBuilder* builder) override;
|
||||
FramebufferBase* CreateFramebuffer(FramebufferBuilder* builder) override;
|
||||
PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override;
|
||||
QueueBase* CreateQueue(QueueBuilder* builder) override;
|
||||
RenderPassBase* CreateRenderPass(RenderPassBuilder* builder) override;
|
||||
RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
|
||||
SamplerBase* CreateSampler(SamplerBuilder* builder) override;
|
||||
ShaderModuleBase* CreateShaderModule(ShaderModuleBuilder* builder) override;
|
||||
SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override;
|
||||
TextureBase* CreateTexture(TextureBuilder* builder) override;
|
||||
TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override;
|
||||
|
||||
void TickImpl() override;
|
||||
void TickImpl() override;
|
||||
|
||||
id<MTLDevice> GetMTLDevice();
|
||||
id<MTLDevice> GetMTLDevice();
|
||||
|
||||
id<MTLCommandBuffer> GetPendingCommandBuffer();
|
||||
void SubmitPendingCommandBuffer();
|
||||
Serial GetPendingCommandSerial();
|
||||
id<MTLCommandBuffer> GetPendingCommandBuffer();
|
||||
void SubmitPendingCommandBuffer();
|
||||
Serial GetPendingCommandSerial();
|
||||
|
||||
MapReadRequestTracker* GetMapReadTracker() const;
|
||||
ResourceUploader* GetResourceUploader() const;
|
||||
MapReadRequestTracker* GetMapReadTracker() const;
|
||||
ResourceUploader* GetResourceUploader() const;
|
||||
|
||||
private:
|
||||
void OnCompletedHandler();
|
||||
private:
|
||||
void OnCompletedHandler();
|
||||
|
||||
id<MTLDevice> mMtlDevice = nil;
|
||||
id<MTLCommandQueue> mCommandQueue = nil;
|
||||
MapReadRequestTracker* mMapReadTracker;
|
||||
ResourceUploader* mResourceUploader;
|
||||
id<MTLDevice> mMtlDevice = nil;
|
||||
id<MTLCommandQueue> mCommandQueue = nil;
|
||||
MapReadRequestTracker* mMapReadTracker;
|
||||
ResourceUploader* mResourceUploader;
|
||||
|
||||
Serial mFinishedCommandSerial = 0;
|
||||
Serial mPendingCommandSerial = 1;
|
||||
id<MTLCommandBuffer> mPendingCommands = nil;
|
||||
Serial mFinishedCommandSerial = 0;
|
||||
Serial mPendingCommandSerial = 1;
|
||||
id<MTLCommandBuffer> mPendingCommands = nil;
|
||||
};
|
||||
|
||||
class BindGroup : public BindGroupBase {
|
||||
public:
|
||||
BindGroup(BindGroupBuilder* builder);
|
||||
public:
|
||||
BindGroup(BindGroupBuilder* builder);
|
||||
};
|
||||
|
||||
class BindGroupLayout : public BindGroupLayoutBase {
|
||||
public:
|
||||
BindGroupLayout(BindGroupLayoutBuilder* builder);
|
||||
public:
|
||||
BindGroupLayout(BindGroupLayoutBuilder* builder);
|
||||
};
|
||||
|
||||
class Framebuffer : public FramebufferBase {
|
||||
public:
|
||||
Framebuffer(FramebufferBuilder* builder);
|
||||
~Framebuffer();
|
||||
public:
|
||||
Framebuffer(FramebufferBuilder* builder);
|
||||
~Framebuffer();
|
||||
};
|
||||
|
||||
class Queue : public QueueBase {
|
||||
public:
|
||||
Queue(QueueBuilder* builder);
|
||||
~Queue();
|
||||
public:
|
||||
Queue(QueueBuilder* builder);
|
||||
~Queue();
|
||||
|
||||
id<MTLCommandQueue> GetMTLCommandQueue();
|
||||
id<MTLCommandQueue> GetMTLCommandQueue();
|
||||
|
||||
// NXT API
|
||||
void Submit(uint32_t numCommands, CommandBuffer* const * commands);
|
||||
// NXT API
|
||||
void Submit(uint32_t numCommands, CommandBuffer* const* commands);
|
||||
|
||||
private:
|
||||
id<MTLCommandQueue> mCommandQueue = nil;
|
||||
private:
|
||||
id<MTLCommandQueue> mCommandQueue = nil;
|
||||
};
|
||||
|
||||
class RenderPass : public RenderPassBase {
|
||||
public:
|
||||
RenderPass(RenderPassBuilder* builder);
|
||||
~RenderPass();
|
||||
public:
|
||||
RenderPass(RenderPassBuilder* builder);
|
||||
~RenderPass();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
||||
#endif // BACKEND_METAL_METALBACKEND_H_
|
||||
#endif // BACKEND_METAL_METALBACKEND_H_
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
#include "backend/metal/ComputePipelineMTL.h"
|
||||
#include "backend/metal/DepthStencilStateMTL.h"
|
||||
#include "backend/metal/InputStateMTL.h"
|
||||
#include "backend/metal/RenderPipelineMTL.h"
|
||||
#include "backend/metal/PipelineLayoutMTL.h"
|
||||
#include "backend/metal/RenderPipelineMTL.h"
|
||||
#include "backend/metal/ResourceUploader.h"
|
||||
#include "backend/metal/SamplerMTL.h"
|
||||
#include "backend/metal/ShaderModuleMTL.h"
|
||||
|
@ -30,8 +30,7 @@
|
|||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
nxtProcTable GetNonValidatingProcs();
|
||||
nxtProcTable GetValidatingProcs();
|
||||
|
||||
|
@ -45,18 +44,18 @@ namespace metal {
|
|||
// Device
|
||||
|
||||
Device::Device(id<MTLDevice> mtlDevice)
|
||||
: mMtlDevice(mtlDevice), mMapReadTracker(new MapReadRequestTracker(this)),
|
||||
mResourceUploader(new ResourceUploader(this)) {
|
||||
: mMtlDevice(mtlDevice),
|
||||
mMapReadTracker(new MapReadRequestTracker(this)),
|
||||
mResourceUploader(new ResourceUploader(this)) {
|
||||
[mMtlDevice retain];
|
||||
mCommandQueue = [mMtlDevice newCommandQueue];
|
||||
}
|
||||
|
||||
Device::~Device() {
|
||||
// Wait for all commands to be finished so we can free resources
|
||||
// SubmitPendingCommandBuffer may not increment the pendingCommandSerial if there
|
||||
// are no pending commands, so we can't store the pendingSerial before
|
||||
// SubmitPendingCommandBuffer then wait for it to be passed. Instead we submit and
|
||||
// wait for the serial before the next pendingCommandSerial.
|
||||
// Wait for all commands to be finished so we can free resources SubmitPendingCommandBuffer
|
||||
// may not increment the pendingCommandSerial if there are no pending commands, so we can't
|
||||
// store the pendingSerial before SubmitPendingCommandBuffer then wait for it to be passed.
|
||||
// Instead we submit and wait for the serial before the next pendingCommandSerial.
|
||||
SubmitPendingCommandBuffer();
|
||||
while (mFinishedCommandSerial != mPendingCommandSerial - 1) {
|
||||
usleep(100);
|
||||
|
@ -165,7 +164,8 @@ namespace metal {
|
|||
|
||||
// Ok, ObjC blocks are weird. My understanding is that local variables are captured by value
|
||||
// so this-> works as expected. However it is unclear how members are captured, (are they
|
||||
// captured using this-> or by value?) so we make a copy of the pendingCommandSerial on the stack.
|
||||
// captured using this-> or by value?) so we make a copy of the pendingCommandSerial on the
|
||||
// stack.
|
||||
Serial pendingSerial = mPendingCommandSerial;
|
||||
[mPendingCommands addCompletedHandler:^(id<MTLCommandBuffer>) {
|
||||
this->mFinishedCommandSerial = pendingSerial;
|
||||
|
@ -174,14 +174,14 @@ namespace metal {
|
|||
[mPendingCommands commit];
|
||||
[mPendingCommands release];
|
||||
mPendingCommands = nil;
|
||||
mPendingCommandSerial ++;
|
||||
mPendingCommandSerial++;
|
||||
}
|
||||
|
||||
uint64_t Device::GetPendingCommandSerial() {
|
||||
// If this is called, then it means some piece of code somewhere will wait for this serial to
|
||||
// complete. Make sure the pending command buffer is created so that it is on the worst case
|
||||
// enqueued on the next Tick() and eventually increments the serial. Otherwise if no GPU work
|
||||
// happens we could be waiting for this serial forever.
|
||||
// If this is called, then it means some piece of code somewhere will wait for this serial
|
||||
// to complete. Make sure the pending command buffer is created so that it is on the worst
|
||||
// case enqueued on the next Tick() and eventually increments the serial. Otherwise if no
|
||||
// GPU work happens we could be waiting for this serial forever.
|
||||
GetPendingCommandBuffer();
|
||||
return mPendingCommandSerial;
|
||||
}
|
||||
|
@ -196,8 +196,7 @@ namespace metal {
|
|||
|
||||
// Bind Group
|
||||
|
||||
BindGroup::BindGroup(BindGroupBuilder* builder)
|
||||
: BindGroupBase(builder) {
|
||||
BindGroup::BindGroup(BindGroupBuilder* builder) : BindGroupBase(builder) {
|
||||
}
|
||||
|
||||
// Bind Group Layout
|
||||
|
@ -208,8 +207,7 @@ namespace metal {
|
|||
|
||||
// Framebuffer
|
||||
|
||||
Framebuffer::Framebuffer(FramebufferBuilder* builder)
|
||||
: FramebufferBase(builder) {
|
||||
Framebuffer::Framebuffer(FramebufferBuilder* builder) : FramebufferBase(builder) {
|
||||
}
|
||||
|
||||
Framebuffer::~Framebuffer() {
|
||||
|
@ -217,8 +215,7 @@ namespace metal {
|
|||
|
||||
// Queue
|
||||
|
||||
Queue::Queue(QueueBuilder* builder)
|
||||
: QueueBase(builder) {
|
||||
Queue::Queue(QueueBuilder* builder) : QueueBase(builder) {
|
||||
Device* device = ToBackend(builder->GetDevice());
|
||||
mCommandQueue = [device->GetMTLDevice() newCommandQueue];
|
||||
}
|
||||
|
@ -232,7 +229,7 @@ namespace metal {
|
|||
return mCommandQueue;
|
||||
}
|
||||
|
||||
void Queue::Submit(uint32_t numCommands, CommandBuffer* const * commands) {
|
||||
void Queue::Submit(uint32_t numCommands, CommandBuffer* const* commands) {
|
||||
Device* device = ToBackend(GetDevice());
|
||||
id<MTLCommandBuffer> commandBuffer = device->GetPendingCommandBuffer();
|
||||
|
||||
|
@ -245,12 +242,10 @@ namespace metal {
|
|||
|
||||
// RenderPass
|
||||
|
||||
RenderPass::RenderPass(RenderPassBuilder* builder)
|
||||
: RenderPassBase(builder) {
|
||||
RenderPass::RenderPass(RenderPassBuilder* builder) : RenderPassBase(builder) {
|
||||
}
|
||||
|
||||
RenderPass::~RenderPass() {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
|
|
@ -25,21 +25,20 @@ namespace spirv_cross {
|
|||
class CompilerMSL;
|
||||
}
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
class PipelineLayout : public PipelineLayoutBase {
|
||||
public:
|
||||
PipelineLayout(PipelineLayoutBuilder* builder);
|
||||
public:
|
||||
PipelineLayout(PipelineLayoutBuilder* builder);
|
||||
|
||||
using BindingIndexInfo = std::array<std::array<uint32_t, kMaxBindingsPerGroup>, kMaxBindGroups>;
|
||||
const BindingIndexInfo& GetBindingIndexInfo(nxt::ShaderStage stage) const;
|
||||
using BindingIndexInfo =
|
||||
std::array<std::array<uint32_t, kMaxBindingsPerGroup>, kMaxBindGroups>;
|
||||
const BindingIndexInfo& GetBindingIndexInfo(nxt::ShaderStage stage) const;
|
||||
|
||||
private:
|
||||
PerStage<BindingIndexInfo> mIndexInfo;
|
||||
private:
|
||||
PerStage<BindingIndexInfo> mIndexInfo;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
||||
#endif // BACKEND_METAL_PIPELINELAYOUTMTL_H_
|
||||
#endif // BACKEND_METAL_PIPELINELAYOUTMTL_H_
|
||||
|
|
|
@ -16,11 +16,9 @@
|
|||
|
||||
#include "backend/metal/MetalBackend.h"
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
PipelineLayout::PipelineLayout(PipelineLayoutBuilder* builder)
|
||||
: PipelineLayoutBase(builder) {
|
||||
PipelineLayout::PipelineLayout(PipelineLayoutBuilder* builder) : PipelineLayoutBase(builder) {
|
||||
// Each stage has its own numbering namespace in CompilerMSL.
|
||||
for (auto stage : IterateStages(kAllStages)) {
|
||||
// Buffer number 0 is reserved for push constants
|
||||
|
@ -58,9 +56,9 @@ namespace metal {
|
|||
}
|
||||
}
|
||||
|
||||
const PipelineLayout::BindingIndexInfo& PipelineLayout::GetBindingIndexInfo(nxt::ShaderStage stage) const {
|
||||
const PipelineLayout::BindingIndexInfo& PipelineLayout::GetBindingIndexInfo(
|
||||
nxt::ShaderStage stage) const {
|
||||
return mIndexInfo[stage];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
|
|
@ -19,26 +19,24 @@
|
|||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
class RenderPipeline : public RenderPipelineBase {
|
||||
public:
|
||||
RenderPipeline(RenderPipelineBuilder* builder);
|
||||
~RenderPipeline();
|
||||
public:
|
||||
RenderPipeline(RenderPipelineBuilder* builder);
|
||||
~RenderPipeline();
|
||||
|
||||
MTLIndexType GetMTLIndexType() const;
|
||||
MTLPrimitiveType GetMTLPrimitiveTopology() const;
|
||||
MTLIndexType GetMTLIndexType() const;
|
||||
MTLPrimitiveType GetMTLPrimitiveTopology() const;
|
||||
|
||||
void Encode(id<MTLRenderCommandEncoder> encoder);
|
||||
void Encode(id<MTLRenderCommandEncoder> encoder);
|
||||
|
||||
private:
|
||||
MTLIndexType mMtlIndexType;
|
||||
MTLPrimitiveType mMtlPrimitiveTopology;
|
||||
id<MTLRenderPipelineState> mMtlRenderPipelineState = nil;
|
||||
private:
|
||||
MTLIndexType mMtlIndexType;
|
||||
MTLPrimitiveType mMtlPrimitiveTopology;
|
||||
id<MTLRenderPipelineState> mMtlRenderPipelineState = nil;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
||||
#endif // BACKEND_METAL_RENDERPIPELINEMTL_H_
|
||||
#endif // BACKEND_METAL_RENDERPIPELINEMTL_H_
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
#include "backend/metal/ShaderModuleMTL.h"
|
||||
#include "backend/metal/TextureMTL.h"
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
namespace {
|
||||
MTLPrimitiveType MTLPrimitiveTopology(nxt::PrimitiveTopology primitiveTopology) {
|
||||
|
@ -41,7 +40,8 @@ namespace metal {
|
|||
}
|
||||
}
|
||||
|
||||
MTLPrimitiveTopologyClass MTLInputPrimitiveTopology(nxt::PrimitiveTopology primitiveTopology) {
|
||||
MTLPrimitiveTopologyClass MTLInputPrimitiveTopology(
|
||||
nxt::PrimitiveTopology primitiveTopology) {
|
||||
switch (primitiveTopology) {
|
||||
case nxt::PrimitiveTopology::PointList:
|
||||
return MTLPrimitiveTopologyClassPoint;
|
||||
|
@ -68,7 +68,6 @@ namespace metal {
|
|||
: RenderPipelineBase(builder),
|
||||
mMtlIndexType(MTLIndexFormat(GetIndexFormat())),
|
||||
mMtlPrimitiveTopology(MTLPrimitiveTopology(GetPrimitiveTopology())) {
|
||||
|
||||
auto mtlDevice = ToBackend(builder->GetDevice())->GetMTLDevice();
|
||||
|
||||
MTLRenderPipelineDescriptor* descriptor = [MTLRenderPipelineDescriptor new];
|
||||
|
@ -77,7 +76,8 @@ namespace metal {
|
|||
const auto& module = ToBackend(builder->GetStageInfo(stage).module);
|
||||
|
||||
const auto& entryPoint = builder->GetStageInfo(stage).entryPoint;
|
||||
id<MTLFunction> function = module->GetFunction(entryPoint.c_str(), ToBackend(GetLayout())).function;
|
||||
id<MTLFunction> function =
|
||||
module->GetFunction(entryPoint.c_str(), ToBackend(GetLayout())).function;
|
||||
|
||||
switch (stage) {
|
||||
case nxt::ShaderStage::Vertex:
|
||||
|
@ -95,7 +95,8 @@ namespace metal {
|
|||
auto& subpassInfo = renderPass->GetSubpassInfo(GetSubPass());
|
||||
|
||||
if (subpassInfo.depthStencilAttachmentSet) {
|
||||
const auto& attachmentInfo = renderPass->GetAttachmentInfo(subpassInfo.depthStencilAttachment);
|
||||
const auto& attachmentInfo =
|
||||
renderPass->GetAttachmentInfo(subpassInfo.depthStencilAttachment);
|
||||
descriptor.depthAttachmentPixelFormat = MetalPixelFormat(attachmentInfo.format);
|
||||
descriptor.stencilAttachmentPixelFormat = MetalPixelFormat(attachmentInfo.format);
|
||||
}
|
||||
|
@ -104,8 +105,10 @@ namespace metal {
|
|||
uint32_t attachment = subpassInfo.colorAttachments[attachmentSlot];
|
||||
const auto& attachmentInfo = renderPass->GetAttachmentInfo(attachment);
|
||||
|
||||
descriptor.colorAttachments[attachmentSlot].pixelFormat = MetalPixelFormat(attachmentInfo.format);
|
||||
ToBackend(GetBlendState(attachmentSlot))->ApplyBlendState(descriptor.colorAttachments[attachmentSlot]);
|
||||
descriptor.colorAttachments[attachmentSlot].pixelFormat =
|
||||
MetalPixelFormat(attachmentInfo.format);
|
||||
ToBackend(GetBlendState(attachmentSlot))
|
||||
->ApplyBlendState(descriptor.colorAttachments[attachmentSlot]);
|
||||
}
|
||||
|
||||
descriptor.inputPrimitiveTopology = MTLInputPrimitiveTopology(GetPrimitiveTopology());
|
||||
|
@ -115,9 +118,9 @@ namespace metal {
|
|||
|
||||
// TODO(kainino@chromium.org): push constants, textures, samplers
|
||||
|
||||
NSError *error = nil;
|
||||
mMtlRenderPipelineState = [mtlDevice
|
||||
newRenderPipelineStateWithDescriptor:descriptor error:&error];
|
||||
NSError* error = nil;
|
||||
mMtlRenderPipelineState =
|
||||
[mtlDevice newRenderPipelineStateWithDescriptor:descriptor error:&error];
|
||||
if (error != nil) {
|
||||
NSLog(@" error => %@", error);
|
||||
builder->HandleError("Error creating pipeline state");
|
||||
|
@ -144,5 +147,4 @@ namespace metal {
|
|||
[encoder setRenderPipelineState:mMtlRenderPipelineState];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
|
|
@ -20,26 +20,23 @@
|
|||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
class Device;
|
||||
|
||||
class ResourceUploader {
|
||||
public:
|
||||
ResourceUploader(Device* device);
|
||||
~ResourceUploader();
|
||||
public:
|
||||
ResourceUploader(Device* device);
|
||||
~ResourceUploader();
|
||||
|
||||
void BufferSubData(id<MTLBuffer> buffer, uint32_t start, uint32_t size, const void* data);
|
||||
void Tick(Serial finishedSerial);
|
||||
void BufferSubData(id<MTLBuffer> buffer, uint32_t start, uint32_t size, const void* data);
|
||||
void Tick(Serial finishedSerial);
|
||||
|
||||
private:
|
||||
Device* mDevice;
|
||||
SerialQueue<id<MTLBuffer>> mInflightUploadBuffers;
|
||||
private:
|
||||
Device* mDevice;
|
||||
SerialQueue<id<MTLBuffer>> mInflightUploadBuffers;
|
||||
};
|
||||
|
||||
}} // namespace backend::metal
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BACKEND_METAL_RESOURCEUPLOADER_H_
|
||||
#endif // BACKEND_METAL_RESOURCEUPLOADER_H_
|
||||
|
|
|
@ -16,30 +16,32 @@
|
|||
|
||||
#include "backend/metal/MetalBackend.h"
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
ResourceUploader::ResourceUploader(Device* device)
|
||||
: mDevice(device) {
|
||||
ResourceUploader::ResourceUploader(Device* device) : mDevice(device) {
|
||||
}
|
||||
|
||||
ResourceUploader::~ResourceUploader() {
|
||||
ASSERT(mInflightUploadBuffers.Empty());
|
||||
}
|
||||
|
||||
void ResourceUploader::BufferSubData(id<MTLBuffer> buffer, uint32_t start, uint32_t size, const void* data) {
|
||||
// TODO(cwallez@chromium.org) use a ringbuffer instead of creating a small buffer for each update
|
||||
id<MTLBuffer> uploadBuffer = [mDevice->GetMTLDevice() newBufferWithLength:size
|
||||
options:MTLResourceStorageModeShared];
|
||||
void ResourceUploader::BufferSubData(id<MTLBuffer> buffer,
|
||||
uint32_t start,
|
||||
uint32_t size,
|
||||
const void* data) {
|
||||
// TODO(cwallez@chromium.org) use a ringbuffer instead of creating a small buffer for each
|
||||
// update
|
||||
id<MTLBuffer> uploadBuffer =
|
||||
[mDevice->GetMTLDevice() newBufferWithLength:size options:MTLResourceStorageModeShared];
|
||||
memcpy([uploadBuffer contents], data, size);
|
||||
|
||||
id<MTLCommandBuffer> commandBuffer = mDevice->GetPendingCommandBuffer();
|
||||
id<MTLBlitCommandEncoder> encoder = [commandBuffer blitCommandEncoder];
|
||||
[encoder copyFromBuffer:uploadBuffer
|
||||
sourceOffset:0
|
||||
toBuffer:buffer
|
||||
destinationOffset:start
|
||||
size:size];
|
||||
sourceOffset:0
|
||||
toBuffer:buffer
|
||||
destinationOffset:start
|
||||
size:size];
|
||||
[encoder endEncoding];
|
||||
|
||||
mInflightUploadBuffers.Enqueue(uploadBuffer, mDevice->GetPendingCommandSerial());
|
||||
|
@ -52,5 +54,4 @@ namespace metal {
|
|||
mInflightUploadBuffers.ClearUpTo(finishedSerial);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
|
|
@ -19,21 +19,19 @@
|
|||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
class Sampler : public SamplerBase {
|
||||
public:
|
||||
Sampler(SamplerBuilder* builder);
|
||||
~Sampler();
|
||||
public:
|
||||
Sampler(SamplerBuilder* builder);
|
||||
~Sampler();
|
||||
|
||||
id<MTLSamplerState> GetMTLSamplerState();
|
||||
id<MTLSamplerState> GetMTLSamplerState();
|
||||
|
||||
private:
|
||||
id<MTLSamplerState> mMtlSamplerState = nil;
|
||||
private:
|
||||
id<MTLSamplerState> mMtlSamplerState = nil;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
||||
#endif // BACKEND_METAL_SAMPLERMTL_H_
|
||||
#endif // BACKEND_METAL_SAMPLERMTL_H_
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
|
||||
#include "backend/metal/MetalBackend.h"
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
namespace {
|
||||
MTLSamplerMinMagFilter FilterModeToMinMagFilter(nxt::FilterMode mode) {
|
||||
|
@ -39,8 +38,7 @@ namespace metal {
|
|||
}
|
||||
}
|
||||
|
||||
Sampler::Sampler(SamplerBuilder* builder)
|
||||
: SamplerBase(builder) {
|
||||
Sampler::Sampler(SamplerBuilder* builder) : SamplerBase(builder) {
|
||||
auto desc = [MTLSamplerDescriptor new];
|
||||
[desc autorelease];
|
||||
desc.minFilter = FilterModeToMinMagFilter(builder->GetMinFilter());
|
||||
|
@ -60,5 +58,4 @@ namespace metal {
|
|||
return mMtlSamplerState;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
|
|
@ -23,29 +23,27 @@ namespace spirv_cross {
|
|||
class CompilerMSL;
|
||||
}
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
class PipelineLayout;
|
||||
|
||||
class ShaderModule : public ShaderModuleBase {
|
||||
public:
|
||||
ShaderModule(ShaderModuleBuilder* builder);
|
||||
public:
|
||||
ShaderModule(ShaderModuleBuilder* builder);
|
||||
|
||||
struct MetalFunctionData {
|
||||
id<MTLFunction> function;
|
||||
MTLSize localWorkgroupSize;
|
||||
};
|
||||
MetalFunctionData GetFunction(const char* functionName, const PipelineLayout* layout) const;
|
||||
struct MetalFunctionData {
|
||||
id<MTLFunction> function;
|
||||
MTLSize localWorkgroupSize;
|
||||
};
|
||||
MetalFunctionData GetFunction(const char* functionName, const PipelineLayout* layout) const;
|
||||
|
||||
private:
|
||||
// Calling compile on CompilerMSL somehow changes internal state that makes subsequent
|
||||
// compiles return invalid MSL. We keep the spirv around and recreate the compiler everytime
|
||||
// we need to use it.
|
||||
std::vector<uint32_t> mSpirv;
|
||||
private:
|
||||
// Calling compile on CompilerMSL somehow changes internal state that makes subsequent
|
||||
// compiles return invalid MSL. We keep the spirv around and recreate the compiler everytime
|
||||
// we need to use it.
|
||||
std::vector<uint32_t> mSpirv;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
||||
#endif // BACKEND_METAL_SHADERMODULEMTL_H_
|
||||
#endif // BACKEND_METAL_SHADERMODULEMTL_H_
|
||||
|
|
|
@ -21,13 +21,12 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
namespace {
|
||||
|
||||
spv::ExecutionModel SpirvExecutionModelForStage(nxt::ShaderStage stage) {
|
||||
switch(stage) {
|
||||
switch (stage) {
|
||||
case nxt::ShaderStage::Vertex:
|
||||
return spv::ExecutionModelVertex;
|
||||
case nxt::ShaderStage::Fragment:
|
||||
|
@ -38,7 +37,6 @@ namespace metal {
|
|||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ShaderModule::ShaderModule(ShaderModuleBuilder* builder)
|
||||
|
@ -69,10 +67,8 @@ namespace metal {
|
|||
|
||||
// Create one resource binding entry per stage per binding.
|
||||
for (uint32_t group : IterateBitSet(layout->GetBindGroupsLayoutMask())) {
|
||||
|
||||
const auto& bgInfo = layout->GetBindGroupLayout(group)->GetBindingInfo();
|
||||
for (uint32_t binding : IterateBitSet(bgInfo.mask)) {
|
||||
|
||||
for (auto stage : IterateStages(bgInfo.visibilities[binding])) {
|
||||
uint32_t index = layout->GetBindingIndexInfo(stage)[group][binding];
|
||||
|
||||
|
@ -101,13 +97,15 @@ namespace metal {
|
|||
NSString* mslSource = [NSString stringWithFormat:@"%s", msl.c_str()];
|
||||
|
||||
auto mtlDevice = ToBackend(GetDevice())->GetMTLDevice();
|
||||
NSError *error = nil;
|
||||
id<MTLLibrary> library = [mtlDevice newLibraryWithSource:mslSource options:nil error:&error];
|
||||
NSError* error = nil;
|
||||
id<MTLLibrary> library =
|
||||
[mtlDevice newLibraryWithSource:mslSource options:nil error:&error];
|
||||
if (error != nil) {
|
||||
// TODO(cwallez@chromium.org): forward errors to caller
|
||||
NSLog(@"MTLDevice newLibraryWithSource => %@", error);
|
||||
}
|
||||
// TODO(kainino@chromium.org): make this somehow more robust; it needs to behave like clean_func_name:
|
||||
// TODO(kainino@chromium.org): make this somehow more robust; it needs to behave like
|
||||
// clean_func_name:
|
||||
// https://github.com/KhronosGroup/SPIRV-Cross/blob/4e915e8c483e319d0dd7a1fa22318bef28f8cca3/spirv_msl.cpp#L1213
|
||||
if (strcmp(functionName, "main") == 0) {
|
||||
functionName = "main0";
|
||||
|
@ -121,5 +119,4 @@ namespace metal {
|
|||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
|
|
@ -17,21 +17,19 @@
|
|||
|
||||
#include "backend/SwapChain.h"
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
class Device;
|
||||
|
||||
class SwapChain : public SwapChainBase {
|
||||
public:
|
||||
SwapChain(SwapChainBuilder* builder);
|
||||
~SwapChain();
|
||||
public:
|
||||
SwapChain(SwapChainBuilder* builder);
|
||||
~SwapChain();
|
||||
|
||||
protected:
|
||||
TextureBase* GetNextTextureImpl(TextureBuilder* builder) override;
|
||||
protected:
|
||||
TextureBase* GetNextTextureImpl(TextureBuilder* builder) override;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
||||
#endif // BACKEND_METAL_SWAPCHAINGL_H_
|
||||
#endif // BACKEND_METAL_SWAPCHAINGL_H_
|
||||
|
|
|
@ -19,11 +19,9 @@
|
|||
|
||||
#include <nxt/nxt_wsi.h>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
SwapChain::SwapChain(SwapChainBuilder* builder)
|
||||
: SwapChainBase(builder) {
|
||||
SwapChain::SwapChain(SwapChainBuilder* builder) : SwapChainBase(builder) {
|
||||
const auto& im = GetImplementation();
|
||||
nxtWSIContextMetal wsiContext = {};
|
||||
wsiContext.device = ToBackend(GetDevice())->GetMTLDevice();
|
||||
|
@ -46,5 +44,4 @@ namespace metal {
|
|||
return new Texture(builder, nativeTexture);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
|
|
@ -19,31 +19,30 @@
|
|||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
MTLPixelFormat MetalPixelFormat(nxt::TextureFormat format);
|
||||
|
||||
class Texture : public TextureBase {
|
||||
public:
|
||||
Texture(TextureBuilder* builder);
|
||||
Texture(TextureBuilder* builder, id<MTLTexture> mtlTexture);
|
||||
~Texture();
|
||||
public:
|
||||
Texture(TextureBuilder* builder);
|
||||
Texture(TextureBuilder* builder, id<MTLTexture> mtlTexture);
|
||||
~Texture();
|
||||
|
||||
id<MTLTexture> GetMTLTexture();
|
||||
id<MTLTexture> GetMTLTexture();
|
||||
|
||||
void TransitionUsageImpl(nxt::TextureUsageBit currentUsage, nxt::TextureUsageBit targetUsage) override;
|
||||
void TransitionUsageImpl(nxt::TextureUsageBit currentUsage,
|
||||
nxt::TextureUsageBit targetUsage) override;
|
||||
|
||||
private:
|
||||
id<MTLTexture> mMtlTexture = nil;
|
||||
private:
|
||||
id<MTLTexture> mMtlTexture = nil;
|
||||
};
|
||||
|
||||
class TextureView : public TextureViewBase {
|
||||
public:
|
||||
TextureView(TextureViewBuilder* builder);
|
||||
public:
|
||||
TextureView(TextureViewBuilder* builder);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace backend::metal
|
||||
|
||||
#endif // BACKEND_METAL_TEXTUREMTL_H_
|
||||
#endif // BACKEND_METAL_TEXTUREMTL_H_
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
|
||||
#include "backend/metal/MetalBackend.h"
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
|
||||
MTLPixelFormat MetalPixelFormat(nxt::TextureFormat format) {
|
||||
switch (format) {
|
||||
|
@ -34,7 +33,7 @@ namespace metal {
|
|||
|
||||
namespace {
|
||||
MTLTextureUsage MetalTextureUsage(nxt::TextureUsageBit usage) {
|
||||
MTLTextureUsage result = MTLTextureUsageUnknown; // This is 0
|
||||
MTLTextureUsage result = MTLTextureUsageUnknown; // This is 0
|
||||
|
||||
if (usage & (nxt::TextureUsageBit::Storage)) {
|
||||
result |= MTLTextureUsageShaderWrite | MTLTextureUsageShaderRead;
|
||||
|
@ -59,8 +58,7 @@ namespace metal {
|
|||
}
|
||||
}
|
||||
|
||||
Texture::Texture(TextureBuilder* builder)
|
||||
: TextureBase(builder) {
|
||||
Texture::Texture(TextureBuilder* builder) : TextureBase(builder) {
|
||||
auto desc = [MTLTextureDescriptor new];
|
||||
[desc autorelease];
|
||||
desc.textureType = MetalTextureType(GetDimension());
|
||||
|
@ -93,8 +91,7 @@ namespace metal {
|
|||
void Texture::TransitionUsageImpl(nxt::TextureUsageBit, nxt::TextureUsageBit) {
|
||||
}
|
||||
|
||||
TextureView::TextureView(TextureViewBuilder* builder)
|
||||
: TextureViewBase(builder) {
|
||||
TextureView::TextureView(TextureViewBuilder* builder) : TextureViewBase(builder) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace backend::metal
|
||||
|
|
Loading…
Reference in New Issue