mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-06-03 12:27:21 +12:00
do the copy on the GPU
This commit is contained in:
parent
80bd8f54c3
commit
42fc2bb490
3 changed files with 39 additions and 18 deletions
|
@ -51,6 +51,7 @@ class RendererMTL final : public Renderer {
|
||||||
MTL::SamplerState* nearestSampler;
|
MTL::SamplerState* nearestSampler;
|
||||||
MTL::SamplerState* linearSampler;
|
MTL::SamplerState* linearSampler;
|
||||||
MTL::Texture* lightLUTTextureArray;
|
MTL::Texture* lightLUTTextureArray;
|
||||||
|
MTL::DepthStencilState* defaultDepthStencilState;
|
||||||
|
|
||||||
// Pipelines
|
// Pipelines
|
||||||
MTL::RenderPipelineState* displayPipeline;
|
MTL::RenderPipelineState* displayPipeline;
|
||||||
|
@ -104,5 +105,5 @@ class RendererMTL final : public Renderer {
|
||||||
Metal::Texture& getTexture(Metal::Texture& tex);
|
Metal::Texture& getTexture(Metal::Texture& tex);
|
||||||
void setupTextureEnvState(MTL::RenderCommandEncoder* encoder);
|
void setupTextureEnvState(MTL::RenderCommandEncoder* encoder);
|
||||||
void bindTexturesToSlots(MTL::RenderCommandEncoder* encoder);
|
void bindTexturesToSlots(MTL::RenderCommandEncoder* encoder);
|
||||||
void updateLightingLUT();
|
void updateLightingLUT(MTL::RenderCommandEncoder* encoder);
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,7 @@ using namespace PICA;
|
||||||
|
|
||||||
CMRC_DECLARE(RendererMTL);
|
CMRC_DECLARE(RendererMTL);
|
||||||
|
|
||||||
#define LIGHT_LUT_TEXTURE_WIDTH 256
|
const u16 LIGHT_LUT_TEXTURE_WIDTH = 256;
|
||||||
|
|
||||||
// HACK: redefinition...
|
// HACK: redefinition...
|
||||||
PICA::ColorFmt ToColorFormat(u32 format) {
|
PICA::ColorFmt ToColorFormat(u32 format) {
|
||||||
|
@ -117,8 +117,8 @@ void RendererMTL::initGraphicsContext(SDL_Window* window) {
|
||||||
textureDescriptor->setPixelFormat(MTL::PixelFormatR16Uint);
|
textureDescriptor->setPixelFormat(MTL::PixelFormatR16Uint);
|
||||||
textureDescriptor->setWidth(LIGHT_LUT_TEXTURE_WIDTH);
|
textureDescriptor->setWidth(LIGHT_LUT_TEXTURE_WIDTH);
|
||||||
textureDescriptor->setArrayLength(Lights::LUT_Count);
|
textureDescriptor->setArrayLength(Lights::LUT_Count);
|
||||||
textureDescriptor->setUsage(MTL::TextureUsageShaderRead);
|
textureDescriptor->setUsage(MTL::TextureUsageShaderRead | MTL::TextureUsageShaderWrite);
|
||||||
textureDescriptor->setStorageMode(MTL::StorageModeShared);
|
textureDescriptor->setStorageMode(MTL::StorageModePrivate);
|
||||||
|
|
||||||
lightLUTTextureArray = device->newTexture(textureDescriptor);
|
lightLUTTextureArray = device->newTexture(textureDescriptor);
|
||||||
textureDescriptor->release();
|
textureDescriptor->release();
|
||||||
|
@ -224,12 +224,20 @@ void RendererMTL::initGraphicsContext(SDL_Window* window) {
|
||||||
drawPipelineCache.set(device, library, vertexDrawFunction, vertexDescriptor);
|
drawPipelineCache.set(device, library, vertexDrawFunction, vertexDescriptor);
|
||||||
|
|
||||||
// Copy to LUT texture
|
// Copy to LUT texture
|
||||||
MTL::Function* vertexCopyToLutTextureFunction = copyToLutTextureLibrary->newFunction(NS::String::string("vertexCopyToLutTexture", NS::ASCIIStringEncoding));
|
MTL::FunctionConstantValues* constants = MTL::FunctionConstantValues::alloc()->init();
|
||||||
|
constants->setConstantValue(&LIGHT_LUT_TEXTURE_WIDTH, MTL::DataTypeUShort, NS::UInteger(0));
|
||||||
|
|
||||||
|
error = nullptr;
|
||||||
|
MTL::Function* vertexCopyToLutTextureFunction = copyToLutTextureLibrary->newFunction(NS::String::string("vertexCopyToLutTexture", NS::ASCIIStringEncoding), constants, &error);
|
||||||
|
if (error) {
|
||||||
|
Helpers::panic("Error creating copy_to_lut_texture vertex function: %s", error->description()->cString(NS::ASCIIStringEncoding));
|
||||||
|
}
|
||||||
|
constants->release();
|
||||||
|
|
||||||
MTL::RenderPipelineDescriptor* copyToLutTexturePipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
|
MTL::RenderPipelineDescriptor* copyToLutTexturePipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
|
||||||
copyToLutTexturePipelineDescriptor->setVertexFunction(vertexDisplayFunction);
|
copyToLutTexturePipelineDescriptor->setVertexFunction(vertexCopyToLutTextureFunction);
|
||||||
auto* copyToLutTextureColorAttachment = copyToLutTexturePipelineDescriptor->colorAttachments()->object(0);
|
// Disable rasterization
|
||||||
copyToLutTextureColorAttachment->setPixelFormat(MTL::PixelFormat::PixelFormatBGRA8Unorm);
|
copyToLutTexturePipelineDescriptor->setRasterizationEnabled(false);
|
||||||
|
|
||||||
error = nullptr;
|
error = nullptr;
|
||||||
copyToLutTexturePipeline = device->newRenderPipelineState(copyToLutTexturePipelineDescriptor, &error);
|
copyToLutTexturePipeline = device->newRenderPipelineState(copyToLutTexturePipelineDescriptor, &error);
|
||||||
|
@ -242,6 +250,10 @@ void RendererMTL::initGraphicsContext(SDL_Window* window) {
|
||||||
|
|
||||||
// Vertex buffer cache
|
// Vertex buffer cache
|
||||||
vertexBufferCache.set(device);
|
vertexBufferCache.set(device);
|
||||||
|
|
||||||
|
// -------- Depth stencil state --------
|
||||||
|
MTL::DepthStencilDescriptor* depthStencilDescriptor = MTL::DepthStencilDescriptor::alloc()->init();
|
||||||
|
defaultDepthStencilState = device->newDepthStencilState(depthStencilDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererMTL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) {
|
void RendererMTL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) {
|
||||||
|
@ -450,6 +462,12 @@ void RendererMTL::drawVertices(PICA::PrimType primType, std::span<const PICA::Ve
|
||||||
}
|
}
|
||||||
|
|
||||||
beginRenderPassIfNeeded(renderPassDescriptor, colorRenderTarget->texture, (depthStencilRenderTarget ? depthStencilRenderTarget->texture : nullptr));
|
beginRenderPassIfNeeded(renderPassDescriptor, colorRenderTarget->texture, (depthStencilRenderTarget ? depthStencilRenderTarget->texture : nullptr));
|
||||||
|
|
||||||
|
// Update the LUT texture if necessary
|
||||||
|
if (gpu.lightingLUTDirty) {
|
||||||
|
updateLightingLUT(renderCommandEncoder);
|
||||||
|
}
|
||||||
|
|
||||||
renderCommandEncoder->setRenderPipelineState(pipeline);
|
renderCommandEncoder->setRenderPipelineState(pipeline);
|
||||||
renderCommandEncoder->setDepthStencilState(depthStencilState);
|
renderCommandEncoder->setDepthStencilState(depthStencilState);
|
||||||
// If size is < 4KB, use inline vertex data, otherwise use a buffer
|
// If size is < 4KB, use inline vertex data, otherwise use a buffer
|
||||||
|
@ -460,11 +478,6 @@ void RendererMTL::drawVertices(PICA::PrimType primType, std::span<const PICA::Ve
|
||||||
renderCommandEncoder->setVertexBuffer(buffer.buffer, buffer.offset, VERTEX_BUFFER_BINDING_INDEX);
|
renderCommandEncoder->setVertexBuffer(buffer.buffer, buffer.offset, VERTEX_BUFFER_BINDING_INDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the LUT texture if necessary
|
|
||||||
if (gpu.lightingLUTDirty) {
|
|
||||||
updateLightingLUT();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind resources
|
// Bind resources
|
||||||
setupTextureEnvState(renderCommandEncoder);
|
setupTextureEnvState(renderCommandEncoder);
|
||||||
bindTexturesToSlots(renderCommandEncoder);
|
bindTexturesToSlots(renderCommandEncoder);
|
||||||
|
@ -600,7 +613,7 @@ void RendererMTL::bindTexturesToSlots(MTL::RenderCommandEncoder* encoder) {
|
||||||
encoder->setFragmentSamplerState(linearSampler, 3);
|
encoder->setFragmentSamplerState(linearSampler, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RendererMTL::updateLightingLUT() {
|
void RendererMTL::updateLightingLUT(MTL::RenderCommandEncoder* encoder) {
|
||||||
gpu.lightingLUTDirty = false;
|
gpu.lightingLUTDirty = false;
|
||||||
std::array<u16, GPU::LightingLutSize> u16_lightinglut;
|
std::array<u16, GPU::LightingLutSize> u16_lightinglut;
|
||||||
|
|
||||||
|
@ -609,7 +622,14 @@ void RendererMTL::updateLightingLUT() {
|
||||||
u16_lightinglut[i] = value * 65535 / 4095;
|
u16_lightinglut[i] = value * 65535 / 4095;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < Lights::LUT_Count; i++) {
|
//for (int i = 0; i < Lights::LUT_Count; i++) {
|
||||||
lightLUTTextureArray->replaceRegion(MTL::Region(0, 0, LIGHT_LUT_TEXTURE_WIDTH, 1), 0, i, u16_lightinglut.data() + LIGHT_LUT_TEXTURE_WIDTH * i, 0, 0);
|
// lightLUTTextureArray->replaceRegion(MTL::Region(0, 0, LIGHT_LUT_TEXTURE_WIDTH, 1), 0, i, u16_lightinglut.data() + LIGHT_LUT_TEXTURE_WIDTH * i, 0, 0);
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
renderCommandEncoder->setRenderPipelineState(copyToLutTexturePipeline);
|
||||||
|
renderCommandEncoder->setDepthStencilState(defaultDepthStencilState);
|
||||||
|
renderCommandEncoder->setVertexTexture(lightLUTTextureArray, 0);
|
||||||
|
renderCommandEncoder->setVertexBytes(u16_lightinglut.data(), sizeof(u16_lightinglut), 0);
|
||||||
|
|
||||||
|
renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), GPU::LightingLutSize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,6 @@ using namespace metal;
|
||||||
|
|
||||||
constant ushort lutTextureWidth [[function_constant(0)]];
|
constant ushort lutTextureWidth [[function_constant(0)]];
|
||||||
|
|
||||||
vertex void vertexCopyToLutTexture(uint vid [[vertex_id]], constant ushort* data [[buffer(0)]], texture1d_array<ushort, access::write> out [[texture(0)]]) {
|
vertex void vertexCopyToLutTexture(uint vid [[vertex_id]], texture1d_array<ushort, access::write> out [[texture(0)]], constant ushort* data [[buffer(0)]]) {
|
||||||
out.write(data[vid], vid % lutTextureWidth, vid / lutTextureWidth);
|
out.write(data[vid], vid % lutTextureWidth, vid / lutTextureWidth);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue